From 34e93ecffb26ac5ab98ef66bb5ca41c22631dc5b Mon Sep 17 00:00:00 2001 From: Michael Scott Asato Cuthbert Date: Fri, 2 Jan 2026 14:22:43 -1000 Subject: [PATCH 01/13] Remove coding: utf-8 markers --- dist/dist.py | 1 - documentation/docbuild/__init__.py | 1 - documentation/docbuild/documenters.py | 1 - documentation/docbuild/extensions.py | 1 - documentation/docbuild/iterators.py | 1 - documentation/docbuild/make.py | 1 - documentation/docbuild/upload.py | 1 - documentation/docbuild/writers.py | 5 ++-- documentation/nbvalNotebook.py | 1 - documentation/source/conf.py | 1 - documentation/testDocumentation.py | 1 - music21/__init__.py | 1 - music21/_version.py | 2 +- music21/abcFormat/__init__.py | 1 - music21/abcFormat/testFiles.py | 1 - music21/abcFormat/translate.py | 1 - music21/alpha/__init__.py | 1 - music21/alpha/analysis/__init__.py | 1 - music21/alpha/analysis/aligner.py | 1 - music21/alpha/analysis/fixer.py | 1 - music21/alpha/analysis/hasher.py | 1 - music21/alpha/analysis/ornamentRecognizer.py | 1 - music21/alpha/analysis/search.py | 1 - music21/alpha/analysis/testFiles.py | 1 - music21/analysis/__init__.py | 1 - music21/analysis/correlate.py | 1 - music21/analysis/discrete.py | 1 - music21/analysis/elements.py | 1 - music21/analysis/enharmonics.py | 1 - music21/analysis/floatingKey.py | 1 - music21/analysis/harmonicFunction.py | 1 - music21/analysis/metrical.py | 1 - music21/analysis/neoRiemannian.py | 1 - music21/analysis/patel.py | 1 - music21/analysis/pitchAnalysis.py | 1 - music21/analysis/reduceChords.py | 1 - music21/analysis/reduceChordsOld.py | 1 - music21/analysis/reduction.py | 1 - music21/analysis/segmentByRests.py | 1 - music21/analysis/transposition.py | 1 - music21/analysis/windowed.py | 1 - music21/articulations.py | 1 - music21/audioSearch/__init__.py | 1 - music21/audioSearch/recording.py | 1 - music21/audioSearch/scoreFollower.py | 1 - music21/audioSearch/transcriber.py | 1 - music21/bar.py | 1 - music21/base.py | 1 - music21/beam.py | 1 - music21/braille/__init__.py | 1 - music21/braille/basic.py | 1 - music21/braille/examples.py | 1 - music21/braille/lookup.py | 1 - music21/braille/noteGrouping.py | 1 - music21/braille/objects.py | 1 - music21/braille/runAllBrailleTests.py | 1 - music21/braille/segment.py | 1 - music21/braille/test.py | 1 - music21/braille/text.py | 1 - music21/braille/translate.py | 1 - music21/capella/__init__.py | 1 - music21/capella/fromCapellaXML.py | 1 - music21/chord/__init__.py | 1 - music21/chord/tables.py | 1 - music21/chord/tools.py | 1 - music21/clef.py | 1 - music21/common/__init__.py | 1 - music21/common/classTools.py | 1 - music21/common/decorators.py | 1 - music21/common/enums.py | 1 - music21/common/fileTools.py | 29 ++++++++++--------- music21/common/formats.py | 1 - music21/common/misc.py | 1 - music21/common/numberTools.py | 1 - music21/common/objects.py | 1 - music21/common/parallel.py | 1 - music21/common/pathTools.py | 1 - music21/common/stringTools.py | 1 - music21/common/types.py | 1 - music21/common/weakrefTools.py | 1 - music21/configure.py | 1 - music21/converter/__init__.py | 1 - music21/converter/museScore.py | 1 - music21/converter/qmConverter.py | 1 - music21/converter/subConverters.py | 1 - music21/corpus/__init__.py | 1 - music21/corpus/chorales.py | 1 - music21/corpus/corpora.py | 1 - music21/corpus/manager.py | 1 - music21/corpus/testCorpus.py | 1 - music21/corpus/virtual.py | 1 - music21/corpus/work.py | 1 - music21/defaults.py | 1 - music21/derivation.py | 1 - music21/duration.py | 1 - music21/dynamics.py | 1 - music21/editorial.py | 1 - music21/environment.py | 1 - music21/exceptions21.py | 1 - music21/expressions.py | 1 - music21/features/__init__.py | 1 - music21/features/base.py | 1 - music21/features/jSymbolic.py | 1 - music21/features/native.py | 1 - music21/features/outputFormats.py | 1 - music21/figuredBass/__init__.py | 1 - music21/figuredBass/checker.py | 1 - music21/figuredBass/examples.py | 1 - music21/figuredBass/notation.py | 1 - music21/figuredBass/possibility.py | 1 - music21/figuredBass/realizer.py | 1 - music21/figuredBass/realizerScale.py | 1 - music21/figuredBass/resolution.py | 1 - music21/figuredBass/rules.py | 1 - music21/figuredBass/segment.py | 1 - music21/freezeThaw.py | 1 - music21/graph/__init__.py | 1 - music21/graph/axis.py | 1 - music21/graph/findPlot.py | 1 - music21/graph/plot.py | 1 - music21/graph/primitives.py | 1 - music21/graph/utilities.py | 1 - music21/harmony.py | 1 - music21/humdrum/__init__.py | 1 - music21/humdrum/harmparser.py | 1 - music21/humdrum/instruments.py | 1 - music21/humdrum/questions.py | 1 - music21/humdrum/spineParser.py | 1 - music21/humdrum/testFiles.py | 1 - music21/instrument.py | 1 - music21/interval.py | 1 - music21/ipython21/__init__.py | 1 - music21/ipython21/converters.py | 1 - music21/ipython21/ipExtension.py | 1 - music21/ipython21/objects.py | 1 - music21/key.py | 1 - music21/languageExcerpts/__init__.py | 1 - music21/languageExcerpts/instrumentLookup.py | 1 - .../naturalLanguageObjects.py | 1 - music21/layout.py | 1 - music21/lily/__init__.py | 1 - music21/lily/lilyObjects.py | 1 - music21/lily/translate.py | 1 - music21/mei/__init__.py | 1 - music21/mei/base.py | 1 - music21/mei/test_base.py | 1 - music21/metadata/__init__.py | 1 - music21/metadata/bundles.py | 1 - music21/metadata/caching.py | 1 - music21/metadata/primitives.py | 1 - music21/metadata/properties.py | 1 - music21/meter/__init__.py | 1 - music21/meter/base.py | 1 - music21/meter/core.py | 1 - music21/meter/tests.py | 1 - music21/meter/tools.py | 1 - music21/midi/__init__.py | 1 - music21/midi/base.py | 1 - music21/midi/percussion.py | 1 - music21/midi/realtime.py | 1 - music21/midi/translate.py | 1 - music21/musedata/__init__.py | 1 - music21/musedata/base12_26.py | 1 - music21/musedata/base40.py | 1 - music21/musedata/testPrimitive/__init__.py | 1 - .../musedata/testPrimitive/test01/__init__.py | 1 - music21/musedata/translate.py | 1 - music21/musicxml/__init__.py | 1 - music21/musicxml/archiveTools.py | 1 - music21/musicxml/helpers.py | 1 - .../musicxml/lilypondTestSuite/__init__.py | 1 - music21/musicxml/m21ToXml.py | 1 - music21/musicxml/partStaffExporter.py | 1 - music21/musicxml/testFiles.py | 3 +- music21/musicxml/testPrimitive.py | 1 - music21/musicxml/xmlObjects.py | 1 - music21/musicxml/xmlSoundParser.py | 1 - music21/musicxml/xmlToM21.py | 1 - music21/note.py | 1 - music21/noteworthy/__init__.py | 1 - music21/noteworthy/binaryTranslate.py | 1 - music21/noteworthy/translate.py | 1 - music21/omr/__init__.py | 1 - music21/omr/correctors.py | 1 - music21/omr/evaluators.py | 1 - music21/percussion.py | 1 - music21/pitch.py | 1 - music21/prebase.py | 1 - music21/repeat.py | 1 - music21/roman.py | 1 - music21/romanText/__init__.py | 1 - music21/romanText/clercqTemperley.py | 1 - music21/romanText/rtObjects.py | 1 - music21/romanText/testFiles.py | 1 - music21/romanText/translate.py | 1 - music21/romanText/tsvConverter.py | 1 - music21/romanText/writeRoman.py | 1 - music21/scale/__init__.py | 1 - music21/scale/intervalNetwork.py | 1 - music21/scale/scala/__init__.py | 1 - music21/scale/scala/scl/__init__.py | 1 - music21/scale/test_scale_main.py | 1 - music21/search/__init__.py | 1 - music21/search/base.py | 1 - music21/search/lyrics.py | 1 - music21/search/segment.py | 1 - music21/search/serial.py | 1 - music21/serial.py | 1 - music21/sieve.py | 1 - music21/sites.py | 1 - music21/sorting.py | 1 - music21/spanner.py | 1 - music21/stream/__init__.py | 1 - music21/stream/base.py | 1 - music21/stream/core.py | 1 - music21/stream/enums.py | 1 - music21/stream/filters.py | 1 - music21/stream/iterator.py | 1 - music21/stream/makeNotation.py | 1 - music21/stream/streamStatus.py | 1 - music21/stream/tests.py | 1 - music21/stream/tools.py | 1 - music21/style.py | 1 - music21/tablature.py | 1 - music21/tempo.py | 1 - music21/test/commonTest.py | 1 - music21/test/coverageM21.py | 1 - music21/test/memoryUsage.py | 1 - music21/test/multiprocessTest.py | 1 - music21/test/testDefault.py | 1 - music21/test/testExternal.py | 1 - music21/test/testLint.py | 1 - music21/test/testPerformance.py | 1 - music21/test/testRunner.py | 1 - music21/test/testSerialization.py | 1 - music21/test/testSingleCoreAll.py | 1 - music21/test/test_base.py | 1 - music21/test/test_metadata.py | 1 - music21/test/test_pitch.py | 1 - music21/test/timeGraphImportStar.py | 1 - music21/test/timeGraphs.py | 1 - music21/test/toggleDebug.py | 1 - music21/test/treeYield.py | 1 - music21/test/warningMultiprocessTest.py | 1 - music21/text.py | 3 +- music21/tie.py | 1 - music21/tinyNotation.py | 1 - music21/tree/__init__.py | 1 - music21/tree/analysis.py | 1 - music21/tree/core.py | 1 - music21/tree/fromStream.py | 1 - music21/tree/node.py | 1 - music21/tree/spans.py | 1 - music21/tree/timespanTree.py | 3 +- music21/tree/toStream.py | 1 - music21/tree/trees.py | 3 +- music21/tree/verticality.py | 1 - music21/variant.py | 1 - music21/vexflow/__init__.py | 1 - music21/vexflow/toMusic21j.py | 1 - music21/voiceLeading.py | 1 - music21/volpiano.py | 1 - music21/volume.py | 1 - 263 files changed, 22 insertions(+), 282 deletions(-) diff --git a/dist/dist.py b/dist/dist.py index 54b27f6153..bb33b8e52f 100644 --- a/dist/dist.py +++ b/dist/dist.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: dist.py # Purpose: Distribution and uploading script diff --git a/documentation/docbuild/__init__.py b/documentation/docbuild/__init__.py index 9c41f0490a..50b65214a5 100644 --- a/documentation/docbuild/__init__.py +++ b/documentation/docbuild/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- __all__ = ['documenters', 'iterators', 'writers'] from . import documenters diff --git a/documentation/docbuild/documenters.py b/documentation/docbuild/documenters.py index 6ab577ed8e..4baf0400bc 100644 --- a/documentation/docbuild/documenters.py +++ b/documentation/docbuild/documenters.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: documentation/library/documenters.py # Purpose: music21 documentation helper classes for proper formatting diff --git a/documentation/docbuild/extensions.py b/documentation/docbuild/extensions.py index 3b38fc5e55..a488918479 100644 --- a/documentation/docbuild/extensions.py +++ b/documentation/docbuild/extensions.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Name: extensions.py # Purpose: Sphinx extension for hiding and showing lines in docs diff --git a/documentation/docbuild/iterators.py b/documentation/docbuild/iterators.py index 9768155ccc..d5001a9ed0 100644 --- a/documentation/docbuild/iterators.py +++ b/documentation/docbuild/iterators.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: docbuild/iterators.py # Purpose: music21 documentation iterators, including Jupyter notebook to ReST converter diff --git a/documentation/docbuild/make.py b/documentation/docbuild/make.py index 28497d56bd..0a34e9241d 100644 --- a/documentation/docbuild/make.py +++ b/documentation/docbuild/make.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: documentation/make.py # Purpose: music21 documentation script, v. 2.0 diff --git a/documentation/docbuild/upload.py b/documentation/docbuild/upload.py index 1fc6457f61..12b2710255 100644 --- a/documentation/docbuild/upload.py +++ b/documentation/docbuild/upload.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: upload.py # Purpose: music21 documentation upload utility diff --git a/documentation/docbuild/writers.py b/documentation/docbuild/writers.py index c4a8eef574..b967f3e943 100644 --- a/documentation/docbuild/writers.py +++ b/documentation/docbuild/writers.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: docbuild/writers.py # Purpose: music21 documentation writer to rst @@ -361,11 +360,11 @@ def convertOneNotebook(self, jupyterNotebookFilePath): self.runNBConvert(jupyterNotebookFilePath) # uses this convoluted way of reading because 'encoding' was an invalid keyword argument # for the built-in 'open' in old python, and never upgraded. - with rstFilePath.open('r', encoding='utf8') as f: + with rstFilePath.open('r', encoding='utf-8') as f: oldLines = f.read().splitlines() lines = self.cleanConvertedNotebook(oldLines, jupyterNotebookFilePath) - with rstFilePath.open('w', encoding='utf8') as f: + with rstFilePath.open('w', encoding='utf-8') as f: f.write('\n'.join(lines)) return True diff --git a/documentation/nbvalNotebook.py b/documentation/nbvalNotebook.py index 078de643a9..b34317ae06 100644 --- a/documentation/nbvalNotebook.py +++ b/documentation/nbvalNotebook.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- ''' Run tests of notebooks using nbval -- called from testDocumentation diff --git a/documentation/source/conf.py b/documentation/source/conf.py index 470107273a..12b56a78b4 100644 --- a/documentation/source/conf.py +++ b/documentation/source/conf.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # music21 documentation build configuration file, created by # sphinx-quickstart on Fri Jun 14 16:48:40 2013. diff --git a/documentation/testDocumentation.py b/documentation/testDocumentation.py index f32adc7275..2789d22840 100644 --- a/documentation/testDocumentation.py +++ b/documentation/testDocumentation.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: testDocumentation.py # Purpose: tests from or derived from the Documentation diff --git a/music21/__init__.py b/music21/__init__.py index 3133d5bf2b..351446b07c 100644 --- a/music21/__init__.py +++ b/music21/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- ''' The music21 Framework is Copyright © 2006-2026 Michael Scott Asato Cuthbert. diff --git a/music21/_version.py b/music21/_version.py index 72dbfdf646..3f1c7aab38 100644 --- a/music21/_version.py +++ b/music21/_version.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- + ''' This file contains Music21's version number information. diff --git a/music21/abcFormat/__init__.py b/music21/abcFormat/__init__.py index 0484f17e98..8dd819b911 100644 --- a/music21/abcFormat/__init__.py +++ b/music21/abcFormat/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: abc/__init__.py # Purpose: parses ABC Notation diff --git a/music21/abcFormat/testFiles.py b/music21/abcFormat/testFiles.py index 2dc1d864cb..8cbd76cad9 100644 --- a/music21/abcFormat/testFiles.py +++ b/music21/abcFormat/testFiles.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: testFiles.py # Purpose: ABC test files diff --git a/music21/abcFormat/translate.py b/music21/abcFormat/translate.py index 091309f087..3caff8ab65 100644 --- a/music21/abcFormat/translate.py +++ b/music21/abcFormat/translate.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Name: abcFormat.translate.py # Purpose: Translate ABC and music21 objects diff --git a/music21/alpha/__init__.py b/music21/alpha/__init__.py index 719fd1493a..47fd99cbc7 100644 --- a/music21/alpha/__init__.py +++ b/music21/alpha/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Name: alpha/__init__.py # Purpose: music21 modules not fully ready for prime-time diff --git a/music21/alpha/analysis/__init__.py b/music21/alpha/analysis/__init__.py index 8217971ffc..1a03bb1c2a 100644 --- a/music21/alpha/analysis/__init__.py +++ b/music21/alpha/analysis/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import annotations __all__ = [ diff --git a/music21/alpha/analysis/aligner.py b/music21/alpha/analysis/aligner.py index 7a876b6113..321334531f 100644 --- a/music21/alpha/analysis/aligner.py +++ b/music21/alpha/analysis/aligner.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: alpha/analysis/aligner.py # Purpose: A general aligner that tries its best to align two streams diff --git a/music21/alpha/analysis/fixer.py b/music21/alpha/analysis/fixer.py index d13e7663a9..521b5be953 100644 --- a/music21/alpha/analysis/fixer.py +++ b/music21/alpha/analysis/fixer.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: alpha/analysis/fixer.py # Purpose: Fixes two streams given a list of changes between them diff --git a/music21/alpha/analysis/hasher.py b/music21/alpha/analysis/hasher.py index 0c7c9d2e3b..1d3a5892fa 100644 --- a/music21/alpha/analysis/hasher.py +++ b/music21/alpha/analysis/hasher.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: alpha/analysis/hasher.py # Purpose: Hash musical notation diff --git a/music21/alpha/analysis/ornamentRecognizer.py b/music21/alpha/analysis/ornamentRecognizer.py index 51a5e215a3..ac4e0762f9 100644 --- a/music21/alpha/analysis/ornamentRecognizer.py +++ b/music21/alpha/analysis/ornamentRecognizer.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: alpha/analysis/ornamentRecognizer.py # Purpose: Identifies expanded ornaments diff --git a/music21/alpha/analysis/search.py b/music21/alpha/analysis/search.py index 4e0c64d163..209ea469be 100644 --- a/music21/alpha/analysis/search.py +++ b/music21/alpha/analysis/search.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: search.py # Purpose: Tools for searching analysis diff --git a/music21/alpha/analysis/testFiles.py b/music21/alpha/analysis/testFiles.py index 4e0c335bf4..da8001b05d 100644 --- a/music21/alpha/analysis/testFiles.py +++ b/music21/alpha/analysis/testFiles.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: alpha/analysis/testFiles.py # Purpose: consolidated testFiles diff --git a/music21/analysis/__init__.py b/music21/analysis/__init__.py index 08980989a9..defd846ae1 100644 --- a/music21/analysis/__init__.py +++ b/music21/analysis/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import annotations __all__ = [ diff --git a/music21/analysis/correlate.py b/music21/analysis/correlate.py index 480152e89e..f43702b2f2 100644 --- a/music21/analysis/correlate.py +++ b/music21/analysis/correlate.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: correlate.py # Purpose: Stream analyzer designed to correlate and graph two properties diff --git a/music21/analysis/discrete.py b/music21/analysis/discrete.py index 9ede12fda6..149edaca2a 100644 --- a/music21/analysis/discrete.py +++ b/music21/analysis/discrete.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: discrete.py # Purpose: Framework for modular, windowed analysis diff --git a/music21/analysis/elements.py b/music21/analysis/elements.py index 4de4451366..ca9a231731 100644 --- a/music21/analysis/elements.py +++ b/music21/analysis/elements.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: analysis/elements.py # Purpose: Tools for analyzing general elements diff --git a/music21/analysis/enharmonics.py b/music21/analysis/enharmonics.py index 875a8e31cd..8cb66bf098 100644 --- a/music21/analysis/enharmonics.py +++ b/music21/analysis/enharmonics.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: enharmonics.py # Purpose: Tools for returning best enharmonics diff --git a/music21/analysis/floatingKey.py b/music21/analysis/floatingKey.py index 3b221df00a..2569167ca1 100644 --- a/music21/analysis/floatingKey.py +++ b/music21/analysis/floatingKey.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: analysis/floatingKey.py # Purpose: Framework for floating key analysis diff --git a/music21/analysis/harmonicFunction.py b/music21/analysis/harmonicFunction.py index 4037267bc1..cee140a835 100644 --- a/music21/analysis/harmonicFunction.py +++ b/music21/analysis/harmonicFunction.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: harmonicFunction.py # Purpose: Mapping between Roman numeral figures and harmonic function labels diff --git a/music21/analysis/metrical.py b/music21/analysis/metrical.py index 4d015de032..e51023c682 100644 --- a/music21/analysis/metrical.py +++ b/music21/analysis/metrical.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: metrical.py # Purpose: Tools for metrical analysis diff --git a/music21/analysis/neoRiemannian.py b/music21/analysis/neoRiemannian.py index 504de5a096..e16bb731c5 100644 --- a/music21/analysis/neoRiemannian.py +++ b/music21/analysis/neoRiemannian.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: analysis/neoRiemannian.py # Purpose: Neo-Riemannian Chord Transformations diff --git a/music21/analysis/patel.py b/music21/analysis/patel.py index bd400b8a65..58d690e869 100644 --- a/music21/analysis/patel.py +++ b/music21/analysis/patel.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: patel.py # Purpose: Tools for testing Aniruddh D. Patel's analysis theories diff --git a/music21/analysis/pitchAnalysis.py b/music21/analysis/pitchAnalysis.py index fce20998e5..4adc9d4518 100644 --- a/music21/analysis/pitchAnalysis.py +++ b/music21/analysis/pitchAnalysis.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: analysis/pitchAnalysis.py # Purpose: Tools for analyzing pitches diff --git a/music21/analysis/reduceChords.py b/music21/analysis/reduceChords.py index c4d8992865..ec0d477949 100644 --- a/music21/analysis/reduceChords.py +++ b/music21/analysis/reduceChords.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Name: reduceChords.py # Purpose: Tools for eliminating passing chords, etc. diff --git a/music21/analysis/reduceChordsOld.py b/music21/analysis/reduceChordsOld.py index 75741e72ff..16e1d7e9e8 100644 --- a/music21/analysis/reduceChordsOld.py +++ b/music21/analysis/reduceChordsOld.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: reduceChords.py # Purpose: Tools for eliminating passing chords, etc. diff --git a/music21/analysis/reduction.py b/music21/analysis/reduction.py index 5847a74677..7698032eab 100644 --- a/music21/analysis/reduction.py +++ b/music21/analysis/reduction.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: reduction.py # Purpose: Tools for creating a score reduction. diff --git a/music21/analysis/segmentByRests.py b/music21/analysis/segmentByRests.py index 1e42f4a6b4..4241f6f149 100644 --- a/music21/analysis/segmentByRests.py +++ b/music21/analysis/segmentByRests.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: segmentByRests.py # Purpose: Break up a part into its contiguous melodies. diff --git a/music21/analysis/transposition.py b/music21/analysis/transposition.py index edcd46ff27..05a5e538c7 100644 --- a/music21/analysis/transposition.py +++ b/music21/analysis/transposition.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: transposition.py # Purpose: Tools for checking distinct transposition diff --git a/music21/analysis/windowed.py b/music21/analysis/windowed.py index fd530657a7..a0c200ddb0 100644 --- a/music21/analysis/windowed.py +++ b/music21/analysis/windowed.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: windowed.py # Purpose: Framework for modular, windowed analysis diff --git a/music21/articulations.py b/music21/articulations.py index cf337e77cf..ea7020b045 100644 --- a/music21/articulations.py +++ b/music21/articulations.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: articulations.py # Purpose: music21 classes for representing articulations diff --git a/music21/audioSearch/__init__.py b/music21/audioSearch/__init__.py index 171c1ea177..f056fd391b 100644 --- a/music21/audioSearch/__init__.py +++ b/music21/audioSearch/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Name: audioSearch.py # Purpose: base subroutines for all audioSearching and score following diff --git a/music21/audioSearch/recording.py b/music21/audioSearch/recording.py index f1860b8763..64802018b2 100644 --- a/music21/audioSearch/recording.py +++ b/music21/audioSearch/recording.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: audioSearch.recording.py # Purpose: routines for making recordings from microphone input diff --git a/music21/audioSearch/scoreFollower.py b/music21/audioSearch/scoreFollower.py index d44e2a03a0..e705c35f91 100644 --- a/music21/audioSearch/scoreFollower.py +++ b/music21/audioSearch/scoreFollower.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Name: audioSearch.scoreFollower.py # Purpose: Detection of the position in the score in real time diff --git a/music21/audioSearch/transcriber.py b/music21/audioSearch/transcriber.py index 08cba0e402..1f00e13f7e 100644 --- a/music21/audioSearch/transcriber.py +++ b/music21/audioSearch/transcriber.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: audioSearch.transcriber.py # Purpose: Automatically transcribe melodies from a microphone or diff --git a/music21/bar.py b/music21/bar.py index be5dfe059f..ba7c14b43c 100644 --- a/music21/bar.py +++ b/music21/bar.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: bar.py # Purpose: music21 classes for representing bars, repeats, and related diff --git a/music21/base.py b/music21/base.py index a34b48082e..5a1acb8019 100644 --- a/music21/base.py +++ b/music21/base.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Name: base.py # Purpose: Music21 base classes and important utilities diff --git a/music21/beam.py b/music21/beam.py index 8240d1a957..21b659c3e3 100644 --- a/music21/beam.py +++ b/music21/beam.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Name: beam.py # Purpose: music21 classes for representing beams and beam groups diff --git a/music21/braille/__init__.py b/music21/braille/__init__.py index 56cfefe3ae..d861b8fb5f 100644 --- a/music21/braille/__init__.py +++ b/music21/braille/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import annotations __all__ = [ diff --git a/music21/braille/basic.py b/music21/braille/basic.py index 0ff219b696..aae0121d71 100644 --- a/music21/braille/basic.py +++ b/music21/braille/basic.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: basic.py # Purpose: music21 class which allows transcription of music21Object instances to braille. diff --git a/music21/braille/examples.py b/music21/braille/examples.py index f212cab100..815e0f3cbb 100644 --- a/music21/braille/examples.py +++ b/music21/braille/examples.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: examples.py # Purpose: Transcribing popular music into braille music using music21. diff --git a/music21/braille/lookup.py b/music21/braille/lookup.py index b887c3bb6b..66f8c5e38b 100644 --- a/music21/braille/lookup.py +++ b/music21/braille/lookup.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ---------------------------------------------------------------------------------- # Name: lookup.py # Purpose: music21 class which contains lookup tables between print and braille diff --git a/music21/braille/noteGrouping.py b/music21/braille/noteGrouping.py index 491f08a327..588a0d255f 100644 --- a/music21/braille/noteGrouping.py +++ b/music21/braille/noteGrouping.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: noteGrouping.py # Purpose: Transcribes note groupings into Braille diff --git a/music21/braille/objects.py b/music21/braille/objects.py index c412bd2d8f..2c3d464621 100644 --- a/music21/braille/objects.py +++ b/music21/braille/objects.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: object.py # Purpose: music21 classes for indicating Braille formatting, etc. diff --git a/music21/braille/runAllBrailleTests.py b/music21/braille/runAllBrailleTests.py index e0237d9813..906ba6e09d 100644 --- a/music21/braille/runAllBrailleTests.py +++ b/music21/braille/runAllBrailleTests.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: braille/runAllBrailleTests.py # Purpose: Test runner for Bo-Cheng Jhan and others who would prefer diff --git a/music21/braille/segment.py b/music21/braille/segment.py index 24d0c16566..f934f3d7c9 100644 --- a/music21/braille/segment.py +++ b/music21/braille/segment.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: segment.py # Purpose: Division of stream.Part into segments for individual handling diff --git a/music21/braille/test.py b/music21/braille/test.py index f614185232..a977586d6e 100644 --- a/music21/braille/test.py +++ b/music21/braille/test.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: test.py # Purpose: Examples from "Introduction to Braille Music Transcription" diff --git a/music21/braille/text.py b/music21/braille/text.py index d5720b2b73..6335f59499 100644 --- a/music21/braille/text.py +++ b/music21/braille/text.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: text.py # Purpose: music21 class which allows for accurate formatting of braille transcription diff --git a/music21/braille/translate.py b/music21/braille/translate.py index 34aa8bb45d..655389d535 100644 --- a/music21/braille/translate.py +++ b/music21/braille/translate.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Name: translate.py # Purpose: music21 class which allows transcription of music21 data to braille diff --git a/music21/capella/__init__.py b/music21/capella/__init__.py index 8c74bf5343..7c511d7f3d 100644 --- a/music21/capella/__init__.py +++ b/music21/capella/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: capella/__init__.py # Purpose: parses Capella music Notation diff --git a/music21/capella/fromCapellaXML.py b/music21/capella/fromCapellaXML.py index 75bed08b6d..d0f502f77c 100644 --- a/music21/capella/fromCapellaXML.py +++ b/music21/capella/fromCapellaXML.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: fromCapellaXML.py # Purpose: Module for importing capellaXML (.capx) files. diff --git a/music21/chord/__init__.py b/music21/chord/__init__.py index 0bc7df3267..376bc9225d 100644 --- a/music21/chord/__init__.py +++ b/music21/chord/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: chord.py # Purpose: Chord representation and utilities diff --git a/music21/chord/tables.py b/music21/chord/tables.py index c15babb279..0dfcee549d 100644 --- a/music21/chord/tables.py +++ b/music21/chord/tables.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: chord.tables.py # Purpose: data and tables for chord and set class processing. diff --git a/music21/chord/tools.py b/music21/chord/tools.py index 9e80e0eaf7..4b8458d9a0 100644 --- a/music21/chord/tools.py +++ b/music21/chord/tools.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: chord/tools.py # Purpose: Chord utilities too obscure to go on the Chord object diff --git a/music21/clef.py b/music21/clef.py index b0b4fcd297..01c442c3c6 100644 --- a/music21/clef.py +++ b/music21/clef.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: clef.py # Purpose: Objects for representing clefs diff --git a/music21/common/__init__.py b/music21/common/__init__.py index 2c5f6c7883..bea3d4a4c7 100644 --- a/music21/common/__init__.py +++ b/music21/common/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: common.py # Purpose: Basic Utilities diff --git a/music21/common/classTools.py b/music21/common/classTools.py index 77a25bb342..bdd3914c10 100644 --- a/music21/common/classTools.py +++ b/music21/common/classTools.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: common/classTools.py # Purpose: Utilities for classes diff --git a/music21/common/decorators.py b/music21/common/decorators.py index 73f9b7a381..d10cd5eeff 100644 --- a/music21/common/decorators.py +++ b/music21/common/decorators.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: common/decorators.py # Purpose: Decorators for functions diff --git a/music21/common/enums.py b/music21/common/enums.py index 640c40825c..634ba646c1 100644 --- a/music21/common/enums.py +++ b/music21/common/enums.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: common/enums.py # Purpose: Music21 Enumerations diff --git a/music21/common/fileTools.py b/music21/common/fileTools.py index 55b07452d3..8fabcb5ef9 100644 --- a/music21/common/fileTools.py +++ b/music21/common/fileTools.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: common/fileTools.py # Purpose: Utilities for files @@ -79,37 +78,39 @@ def readFileEncodingSafe(filePath, firstGuess='utf-8') -> str: # noinspection PyShadowingNames r''' Slow, but will read a file of unknown encoding as safely as possible using - the chardet package. + the chardet package. Mostly obsolete in the utf-8 world of today, but + useful for older code - Let's try to load this file as ascii -- it has a copyright symbol at the top, - so it won't load in Python3: + Let's try to load the `music21.common.__init__.py` file as ascii -- + it has a copyright symbol near the top, so it won't load in Python3: >>> import os >>> c = str(common.getSourceFilePath() / 'common' / '__init__.py') - >>> #_DOCS_SHOW f = open(c) - >>> #_DOCS_SHOW data = f.read() + >>> f = open(c, encoding='ascii') + >>> data = f.read() Traceback (most recent call last): UnicodeDecodeError: 'ascii' codec can't decode byte 0xc2 in position ...: ordinal not in range(128) - That won't do! now I know that it is in utf-8, but maybe you don't. Or it could - be an old humdrum or Noteworthy file with unknown encoding. This will load it safely. + That won't do! Now I know that it is in utf-8, but maybe you don't. Or it could + be an old Humdrum or Noteworthy file with Windows or unknown encoding. + This will load it as safely as possible. >>> data = common.readFileEncodingSafe(c) - >>> data[0:30] - '# -*- coding: utf-8 -*-\n# ----' + >>> data[83:106] + 'Name: common.py' Well, that's nothing, since the first guess here is utf-8, and it's right. So let's give a worse first guess: >>> data = common.readFileEncodingSafe(c, firstGuess='SHIFT_JIS') # old Japanese standard - >>> data[0:30] - '# -*- coding: utf-8 -*-\n# ----' + >>> data[83:106] + 'Name: common.py' It worked! - Note that this is slow enough if it gets it wrong that the firstGuess should be set - to something reasonable like 'ascii' or 'utf-8'. + Note that trying lots of encodings is slow enough when the first guess is wrong + that the firstGuess should be set to something reasonable like 'utf-8' or 'ascii'. ''' try: with io.open(filePath, 'r', encoding=firstGuess) as thisFile: diff --git a/music21/common/formats.py b/music21/common/formats.py index 8f8dbda1b0..230b67dfbe 100644 --- a/music21/common/formats.py +++ b/music21/common/formats.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: common/formats.py # Purpose: Utilities for formats diff --git a/music21/common/misc.py b/music21/common/misc.py index 11ee483073..88c93dd08e 100644 --- a/music21/common/misc.py +++ b/music21/common/misc.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: common/misc.py # Purpose: Everything that doesn't fit into anything else. diff --git a/music21/common/numberTools.py b/music21/common/numberTools.py index 62be3cfe15..0e24263c0c 100644 --- a/music21/common/numberTools.py +++ b/music21/common/numberTools.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: common/numberTools.py # Purpose: Utilities for working with numbers or number-like objects diff --git a/music21/common/objects.py b/music21/common/objects.py index 3530e029f0..bd169fa697 100644 --- a/music21/common/objects.py +++ b/music21/common/objects.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: common/objects.py # Purpose: Commonly used Objects and Mixins diff --git a/music21/common/parallel.py b/music21/common/parallel.py index 370b86a227..f6942a2471 100644 --- a/music21/common/parallel.py +++ b/music21/common/parallel.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: common/parallel.py # Purpose: Utilities for parallel computing diff --git a/music21/common/pathTools.py b/music21/common/pathTools.py index 13819ccb99..610926d684 100644 --- a/music21/common/pathTools.py +++ b/music21/common/pathTools.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: common/pathTools.py # Purpose: Utilities for paths diff --git a/music21/common/stringTools.py b/music21/common/stringTools.py index b740a4a695..44da9ac031 100644 --- a/music21/common/stringTools.py +++ b/music21/common/stringTools.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: common/stringTools.py # Purpose: Utilities for strings diff --git a/music21/common/types.py b/music21/common/types.py index 1dfc0aeeba..2ee41f4bd8 100644 --- a/music21/common/types.py +++ b/music21/common/types.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: common/types.py # Purpose: Music21 Typing aids diff --git a/music21/common/weakrefTools.py b/music21/common/weakrefTools.py index 5a4971bd60..d1a1daa49c 100644 --- a/music21/common/weakrefTools.py +++ b/music21/common/weakrefTools.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: common/weakrefTools.py # Purpose: Utilities for weak references diff --git a/music21/configure.py b/music21/configure.py index 7f32011925..8045d81505 100644 --- a/music21/configure.py +++ b/music21/configure.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: configure.py # Purpose: Installation and Configuration Utilities diff --git a/music21/converter/__init__.py b/music21/converter/__init__.py index 96db70d145..2ba1837c26 100644 --- a/music21/converter/__init__.py +++ b/music21/converter/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: converter/__init__.py # Purpose: Provide a common way to create Streams from any data music21 diff --git a/music21/converter/museScore.py b/music21/converter/museScore.py index 6f8696d9b1..679e235374 100644 --- a/music21/converter/museScore.py +++ b/music21/converter/museScore.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: converter/museScore.py # Purpose: music21 to MuseScore connection diff --git a/music21/converter/qmConverter.py b/music21/converter/qmConverter.py index 08d91f81da..a2d76be392 100644 --- a/music21/converter/qmConverter.py +++ b/music21/converter/qmConverter.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: converter/qmConverter.py # Purpose: Example of subclassing SubConverter to parse a new format diff --git a/music21/converter/subConverters.py b/music21/converter/subConverters.py index e2f33f37ec..36aadad7a9 100644 --- a/music21/converter/subConverters.py +++ b/music21/converter/subConverters.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: converter/__init__.py # Purpose: Specific subConverters for formats music21 should handle diff --git a/music21/corpus/__init__.py b/music21/corpus/__init__.py index 192ca3becf..500a62ab8e 100644 --- a/music21/corpus/__init__.py +++ b/music21/corpus/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Name: corpus/__init__.py # Purpose: Shortcuts to the corpus collection diff --git a/music21/corpus/chorales.py b/music21/corpus/chorales.py index 044a445e36..09b636e610 100644 --- a/music21/corpus/chorales.py +++ b/music21/corpus/chorales.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: corpus/chorales.py # Purpose: Access to the chorale collection diff --git a/music21/corpus/corpora.py b/music21/corpus/corpora.py index 2d84ab9ab2..2e2b23c7e5 100644 --- a/music21/corpus/corpora.py +++ b/music21/corpus/corpora.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Name: corpora.py # Purpose: corpus classes diff --git a/music21/corpus/manager.py b/music21/corpus/manager.py index 666a7d8e04..1114b9cf96 100644 --- a/music21/corpus/manager.py +++ b/music21/corpus/manager.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Name: corpus/manager.py # Purpose: Manage multiple corpora diff --git a/music21/corpus/testCorpus.py b/music21/corpus/testCorpus.py index 0619b41360..04993128b5 100644 --- a/music21/corpus/testCorpus.py +++ b/music21/corpus/testCorpus.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: corpus/testCorpus.py # Purpose: testing for the corpus diff --git a/music21/corpus/virtual.py b/music21/corpus/virtual.py index 314dcd45c3..599448bd45 100644 --- a/music21/corpus/virtual.py +++ b/music21/corpus/virtual.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: corpus/virtual.py # Purpose: Access to the Virtual corpus collection diff --git a/music21/corpus/work.py b/music21/corpus/work.py index 17e449ff60..6b1aaf0cb1 100644 --- a/music21/corpus/work.py +++ b/music21/corpus/work.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Name: corpus/work.py # Purpose: Manage one work diff --git a/music21/defaults.py b/music21/defaults.py index 39f74e7f99..27019010ba 100644 --- a/music21/defaults.py +++ b/music21/defaults.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: defaults.py # Purpose: Storage for user environment settings and defaults diff --git a/music21/derivation.py b/music21/derivation.py index 633ac941d8..c2db9ce8b5 100644 --- a/music21/derivation.py +++ b/music21/derivation.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Name: derivation.py # Purpose: Class for storing and managing Stream-based derivations diff --git a/music21/duration.py b/music21/duration.py index 11be4bc945..0b5dcc6f04 100644 --- a/music21/duration.py +++ b/music21/duration.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: duration.py # Purpose: music21 classes for representing durations diff --git a/music21/dynamics.py b/music21/dynamics.py index bb7ba8f9af..764667f407 100644 --- a/music21/dynamics.py +++ b/music21/dynamics.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: dynamics.py # Purpose: Module for dealing with dynamics changes. diff --git a/music21/editorial.py b/music21/editorial.py index f2f1e1073e..50c1b99c95 100644 --- a/music21/editorial.py +++ b/music21/editorial.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Name: editorial.py # Purpose: music21 classes for representing editorial information diff --git a/music21/environment.py b/music21/environment.py index 5e219aa60b..e2ce9d0bb0 100644 --- a/music21/environment.py +++ b/music21/environment.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Name: environment.py # Purpose: Storage for user environment settings and defaults diff --git a/music21/exceptions21.py b/music21/exceptions21.py index 4ad6830808..cbb7494260 100644 --- a/music21/exceptions21.py +++ b/music21/exceptions21.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: exceptions21.py # Purpose: music21 Exceptions (called out to not require import music21 to access) diff --git a/music21/expressions.py b/music21/expressions.py index 2330a73e6d..08da2e730c 100644 --- a/music21/expressions.py +++ b/music21/expressions.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: expressions.py # Purpose: Expressions such as Fermatas, etc. diff --git a/music21/features/__init__.py b/music21/features/__init__.py index c43f50f796..d25230c5a7 100644 --- a/music21/features/__init__.py +++ b/music21/features/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: features/__init__.py # Purpose: Feature extractors diff --git a/music21/features/base.py b/music21/features/base.py index 7071c6b46b..61183da4dc 100644 --- a/music21/features/base.py +++ b/music21/features/base.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: features/base.py # Purpose: Feature extractors base classes. diff --git a/music21/features/jSymbolic.py b/music21/features/jSymbolic.py index c2f08d1c48..8bc5c07809 100644 --- a/music21/features/jSymbolic.py +++ b/music21/features/jSymbolic.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: features.jSymbolic.py # Purpose: music21 functions for simple feature extraction diff --git a/music21/features/native.py b/music21/features/native.py index 04954b6c4a..64af40134c 100644 --- a/music21/features/native.py +++ b/music21/features/native.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: features.native.py # Purpose: music21 feature extractors diff --git a/music21/features/outputFormats.py b/music21/features/outputFormats.py index f59be0e993..6b25f38046 100644 --- a/music21/features/outputFormats.py +++ b/music21/features/outputFormats.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import annotations from music21 import environment diff --git a/music21/figuredBass/__init__.py b/music21/figuredBass/__init__.py index d3bd02b97e..16ea0a558c 100644 --- a/music21/figuredBass/__init__.py +++ b/music21/figuredBass/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: figuredBass/__init__.py # Purpose: Figured Bass representation, manipulation, and analysis diff --git a/music21/figuredBass/checker.py b/music21/figuredBass/checker.py index 7f64e803f0..76d8159d5e 100644 --- a/music21/figuredBass/checker.py +++ b/music21/figuredBass/checker.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: checker.py # Purpose: checks figured basses for following voice-leading rules diff --git a/music21/figuredBass/examples.py b/music21/figuredBass/examples.py index a6846546de..ea338c5f36 100644 --- a/music21/figuredBass/examples.py +++ b/music21/figuredBass/examples.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: examples.py # Purpose: Figured bass test cases diff --git a/music21/figuredBass/notation.py b/music21/figuredBass/notation.py index f64a102374..fe8099ec31 100644 --- a/music21/figuredBass/notation.py +++ b/music21/figuredBass/notation.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: notation.py # Purpose: representations of figured bass notation diff --git a/music21/figuredBass/possibility.py b/music21/figuredBass/possibility.py index 47ee9ae665..e116bab33d 100644 --- a/music21/figuredBass/possibility.py +++ b/music21/figuredBass/possibility.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: possibility.py # Purpose: rule checking functions for a "possibility" represented as a tuple. diff --git a/music21/figuredBass/realizer.py b/music21/figuredBass/realizer.py index 160fb33333..853767ca16 100644 --- a/music21/figuredBass/realizer.py +++ b/music21/figuredBass/realizer.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: realizer.py # Purpose: figured bass lines, consisting of notes diff --git a/music21/figuredBass/realizerScale.py b/music21/figuredBass/realizerScale.py index 7a96eb7654..775e53233e 100644 --- a/music21/figuredBass/realizerScale.py +++ b/music21/figuredBass/realizerScale.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: realizerScale.py # Purpose: a figured bass scale diff --git a/music21/figuredBass/resolution.py b/music21/figuredBass/resolution.py index 9b05d08ff5..8dbf6da3a6 100644 --- a/music21/figuredBass/resolution.py +++ b/music21/figuredBass/resolution.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: resolution.py # Purpose: Defines standard resolutions for possibility instances diff --git a/music21/figuredBass/rules.py b/music21/figuredBass/rules.py index 5cef588409..89e7a080be 100644 --- a/music21/figuredBass/rules.py +++ b/music21/figuredBass/rules.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: rules.py # Purpose: Define rules used in realization diff --git a/music21/figuredBass/segment.py b/music21/figuredBass/segment.py index 6c30b7da31..c38ecb1b91 100644 --- a/music21/figuredBass/segment.py +++ b/music21/figuredBass/segment.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: segment.py # Purpose: figured bass note and notational realization. diff --git a/music21/freezeThaw.py b/music21/freezeThaw.py index 4c61990057..2726884b5c 100644 --- a/music21/freezeThaw.py +++ b/music21/freezeThaw.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Name: freezeThaw.py # Purpose: Methods for storing any music21 object on disk. diff --git a/music21/graph/__init__.py b/music21/graph/__init__.py index a7804d3e52..10bf90d459 100644 --- a/music21/graph/__init__.py +++ b/music21/graph/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: graph.py # Purpose: Classes for graphing in matplotlib and/or other graphing tools. diff --git a/music21/graph/axis.py b/music21/graph/axis.py index adcfd3cc14..329c16b269 100644 --- a/music21/graph/axis.py +++ b/music21/graph/axis.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: graph/axis.py # Purpose: Classes for extracting one dimensional data for graphs diff --git a/music21/graph/findPlot.py b/music21/graph/findPlot.py index bf31b67ced..63ec04d377 100644 --- a/music21/graph/findPlot.py +++ b/music21/graph/findPlot.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: graph/findPlot.py # Purpose: Functions that find appropriate plots for graph.plot diff --git a/music21/graph/plot.py b/music21/graph/plot.py index 4185f9ac97..f5fc07b0ed 100644 --- a/music21/graph/plot.py +++ b/music21/graph/plot.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: graph/plots.py # Purpose: Classes for plotting music21 graphs based on Streams. diff --git a/music21/graph/primitives.py b/music21/graph/primitives.py index bf37286827..8fec85c3f5 100644 --- a/music21/graph/primitives.py +++ b/music21/graph/primitives.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: graph/primitives.py # Purpose: Classes for graphing in matplotlib and/or other graphing tools. diff --git a/music21/graph/utilities.py b/music21/graph/utilities.py index 9a399d948d..41cd705b1a 100644 --- a/music21/graph/utilities.py +++ b/music21/graph/utilities.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: graph/utilities.py # Purpose: Functions for finding external modules, manipulating colors, etc. diff --git a/music21/harmony.py b/music21/harmony.py index ed55680f9c..840c6293e9 100644 --- a/music21/harmony.py +++ b/music21/harmony.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: harmony.py # Purpose: music21 classes for representing harmonies and chord symbols diff --git a/music21/humdrum/__init__.py b/music21/humdrum/__init__.py index 92926fc92e..9bd6a2dc39 100644 --- a/music21/humdrum/__init__.py +++ b/music21/humdrum/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: humdrum.__init__.py # Purpose: base module for emulating Humdrum functionality in music21 diff --git a/music21/humdrum/harmparser.py b/music21/humdrum/harmparser.py index 42b315364c..3609bfde8a 100644 --- a/music21/humdrum/harmparser.py +++ b/music21/humdrum/harmparser.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: humdrum.harmparser.py # Purpose: A parser for annotations in **harm spines of Humdrum diff --git a/music21/humdrum/instruments.py b/music21/humdrum/instruments.py index 059cc7fd48..6136f44850 100644 --- a/music21/humdrum/instruments.py +++ b/music21/humdrum/instruments.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: humdrum.instruments.py # Purpose: Instrument Lists for Humdrum and kern in particular diff --git a/music21/humdrum/questions.py b/music21/humdrum/questions.py index eea0921ece..7887c01756 100644 --- a/music21/humdrum/questions.py +++ b/music21/humdrum/questions.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import annotations import unittest diff --git a/music21/humdrum/spineParser.py b/music21/humdrum/spineParser.py index fa716dfc86..3aeef67906 100644 --- a/music21/humdrum/spineParser.py +++ b/music21/humdrum/spineParser.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: humdrum.spineParser.py # Purpose: Conversion and Utility functions for Humdrum and kern in particular diff --git a/music21/humdrum/testFiles.py b/music21/humdrum/testFiles.py index aea9062031..89416e06a8 100644 --- a/music21/humdrum/testFiles.py +++ b/music21/humdrum/testFiles.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import annotations # pylint: disable=line-too-long diff --git a/music21/instrument.py b/music21/instrument.py index 7da5467291..a4ffa68c89 100644 --- a/music21/instrument.py +++ b/music21/instrument.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: instrument.py # Purpose: Class for basic instrument information diff --git a/music21/interval.py b/music21/interval.py index c6d6e24592..5864145bb5 100644 --- a/music21/interval.py +++ b/music21/interval.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: interval.py # Purpose: music21 classes for representing intervals diff --git a/music21/ipython21/__init__.py b/music21/ipython21/__init__.py index 3a16c7ddf6..7e8e2e6560 100644 --- a/music21/ipython21/__init__.py +++ b/music21/ipython21/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: ipython21/__init__.py # Purpose: music21 Jupyter Notebook support diff --git a/music21/ipython21/converters.py b/music21/ipython21/converters.py index d6bf54174e..8eb33595de 100644 --- a/music21/ipython21/converters.py +++ b/music21/ipython21/converters.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: ipython21/converters.py # Purpose: music21 Jupyter Notebook external converters diff --git a/music21/ipython21/ipExtension.py b/music21/ipython21/ipExtension.py index 2f8d123f6f..be579821a5 100644 --- a/music21/ipython21/ipExtension.py +++ b/music21/ipython21/ipExtension.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import annotations from music21 import common diff --git a/music21/ipython21/objects.py b/music21/ipython21/objects.py index 0ddad16d50..84fb882615 100644 --- a/music21/ipython21/objects.py +++ b/music21/ipython21/objects.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- ''' This module is no longer needed in v9 and just kept for historical reasons. ''' diff --git a/music21/key.py b/music21/key.py index 592bdac7ff..3fdbf229ee 100644 --- a/music21/key.py +++ b/music21/key.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: key.py # Purpose: Classes for keys diff --git a/music21/languageExcerpts/__init__.py b/music21/languageExcerpts/__init__.py index 9ed5ae3f49..633ce809b4 100644 --- a/music21/languageExcerpts/__init__.py +++ b/music21/languageExcerpts/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import annotations __all__ = [ diff --git a/music21/languageExcerpts/instrumentLookup.py b/music21/languageExcerpts/instrumentLookup.py index f83340447b..9cd3b3c97a 100644 --- a/music21/languageExcerpts/instrumentLookup.py +++ b/music21/languageExcerpts/instrumentLookup.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: instrumentLookup.py # Purpose: Multi-lingual instrument translation tables diff --git a/music21/languageExcerpts/naturalLanguageObjects.py b/music21/languageExcerpts/naturalLanguageObjects.py index 9f90cddea8..a9a64f0685 100644 --- a/music21/languageExcerpts/naturalLanguageObjects.py +++ b/music21/languageExcerpts/naturalLanguageObjects.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: naturalLanguageObjects.py # Purpose: Multilingual conversion of pitch, etc. objects diff --git a/music21/layout.py b/music21/layout.py index b748cde1c0..3f83def759 100644 --- a/music21/layout.py +++ b/music21/layout.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: layout.py # Purpose: Layout objects diff --git a/music21/lily/__init__.py b/music21/lily/__init__.py index a3f2afe3a2..e9ec4522e8 100644 --- a/music21/lily/__init__.py +++ b/music21/lily/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import annotations __all__ = [ diff --git a/music21/lily/lilyObjects.py b/music21/lily/lilyObjects.py index 21a876aafc..e9281d9231 100644 --- a/music21/lily/lilyObjects.py +++ b/music21/lily/lilyObjects.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: lily/objects.py # Purpose: python objects representing lilypond diff --git a/music21/lily/translate.py b/music21/lily/translate.py index dfba531bcb..4e8c23745e 100644 --- a/music21/lily/translate.py +++ b/music21/lily/translate.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: lily/translate.py # Purpose: music21 classes for translating to Lilypond diff --git a/music21/mei/__init__.py b/music21/mei/__init__.py index b1998e3c99..e018796c6a 100644 --- a/music21/mei/__init__.py +++ b/music21/mei/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Name: mei/__init__.py # Purpose: MEI: The Music Encoding Initiative modules and classes diff --git a/music21/mei/base.py b/music21/mei/base.py index ea25fc15f4..1a09d4380b 100644 --- a/music21/mei/base.py +++ b/music21/mei/base.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Name: mei/base.py # Purpose: Public interfaces for the MEI module diff --git a/music21/mei/test_base.py b/music21/mei/test_base.py index d936909276..adb601144f 100644 --- a/music21/mei/test_base.py +++ b/music21/mei/test_base.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Name: mei/test_main.py # Purpose: Tests for mei/base.py diff --git a/music21/metadata/__init__.py b/music21/metadata/__init__.py index 06443c1934..46deee8000 100755 --- a/music21/metadata/__init__.py +++ b/music21/metadata/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Name: metadata.py # Purpose: music21 classes for representing score and work metadata diff --git a/music21/metadata/bundles.py b/music21/metadata/bundles.py index f6b459a121..d04fabbd73 100644 --- a/music21/metadata/bundles.py +++ b/music21/metadata/bundles.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Name: bundles.py # Purpose: music21 classes for representing score and work metadata diff --git a/music21/metadata/caching.py b/music21/metadata/caching.py index f8caad9c10..33b3f4bd8b 100644 --- a/music21/metadata/caching.py +++ b/music21/metadata/caching.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Name: caching.py # Purpose: music21 classes for representing score and work metadata diff --git a/music21/metadata/primitives.py b/music21/metadata/primitives.py index 504453e5d8..6f36ad760c 100644 --- a/music21/metadata/primitives.py +++ b/music21/metadata/primitives.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Name: primitives.py # Purpose: music21 classes for representing score and work metadata diff --git a/music21/metadata/properties.py b/music21/metadata/properties.py index 2130cdc194..66dc260a6e 100644 --- a/music21/metadata/properties.py +++ b/music21/metadata/properties.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Name: properties.py # Purpose: Data describing the standard set of metadata properties diff --git a/music21/meter/__init__.py b/music21/meter/__init__.py index 525f44c1b9..0fabf58254 100644 --- a/music21/meter/__init__.py +++ b/music21/meter/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Name: meter.py # Purpose: Classes for meters diff --git a/music21/meter/base.py b/music21/meter/base.py index 7addc7ca35..848a9f9448 100644 --- a/music21/meter/base.py +++ b/music21/meter/base.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Name: meter.py # Purpose: Classes for meters diff --git a/music21/meter/core.py b/music21/meter/core.py index f2fd4e89f1..49e8522a37 100644 --- a/music21/meter/core.py +++ b/music21/meter/core.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Name: meter.core.py # Purpose: Component objects for meters diff --git a/music21/meter/tests.py b/music21/meter/tests.py index 403280c4a5..a3c0b85978 100644 --- a/music21/meter/tests.py +++ b/music21/meter/tests.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Name: meter.tests.py # Purpose: Tests of meter diff --git a/music21/meter/tools.py b/music21/meter/tools.py index 3a6629759a..014abbb653 100644 --- a/music21/meter/tools.py +++ b/music21/meter/tools.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Name: meter.tools.py # Purpose: Tools for working with meter diff --git a/music21/midi/__init__.py b/music21/midi/__init__.py index dc60c1458e..5e9c3256d1 100644 --- a/music21/midi/__init__.py +++ b/music21/midi/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: midi/__init__.py # Purpose: Access to MIDI library / music21 classes for dealing with midi data diff --git a/music21/midi/base.py b/music21/midi/base.py index 171c85fcb3..3b14b3f5b8 100644 --- a/music21/midi/base.py +++ b/music21/midi/base.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: midi/__init__.py # Purpose: Access to MIDI library / music21 classes for dealing with midi data diff --git a/music21/midi/percussion.py b/music21/midi/percussion.py index 6d02da859d..ecb7c93996 100644 --- a/music21/midi/percussion.py +++ b/music21/midi/percussion.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: midi/percussion.py # Purpose: music21 classes for representing pitches diff --git a/music21/midi/realtime.py b/music21/midi/realtime.py index 54b693dd7d..206ec2e819 100644 --- a/music21/midi/realtime.py +++ b/music21/midi/realtime.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: midi.realtime.py # Purpose: music21 classes for playing midi data in realtime diff --git a/music21/midi/translate.py b/music21/midi/translate.py index 84a3e6bc8a..585a11723a 100644 --- a/music21/midi/translate.py +++ b/music21/midi/translate.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: midi.translate.py # Purpose: Translate MIDI and music21 objects diff --git a/music21/musedata/__init__.py b/music21/musedata/__init__.py index 478f881951..d2226e4156 100644 --- a/music21/musedata/__init__.py +++ b/music21/musedata/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: musedata/__init__.py # Purpose: parses Walter Hewlett's MuseData format diff --git a/music21/musedata/base12_26.py b/music21/musedata/base12_26.py index 112c39147d..43e79e6d61 100644 --- a/music21/musedata/base12_26.py +++ b/music21/musedata/base12_26.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: base12_26.py # Purpose: Placeholder of Hewlett's base 40 system for 0th and 1st order (base12 and 26). diff --git a/music21/musedata/base40.py b/music21/musedata/base40.py index 2aa9b83912..f9f2761bc9 100644 --- a/music21/musedata/base40.py +++ b/music21/musedata/base40.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: base40.py # Purpose: Base40/Music21 Pitch/Interval Translator diff --git a/music21/musedata/testPrimitive/__init__.py b/music21/musedata/testPrimitive/__init__.py index 40a96afc6f..e69de29bb2 100644 --- a/music21/musedata/testPrimitive/__init__.py +++ b/music21/musedata/testPrimitive/__init__.py @@ -1 +0,0 @@ -# -*- coding: utf-8 -*- diff --git a/music21/musedata/testPrimitive/test01/__init__.py b/music21/musedata/testPrimitive/test01/__init__.py index 40a96afc6f..e69de29bb2 100644 --- a/music21/musedata/testPrimitive/test01/__init__.py +++ b/music21/musedata/testPrimitive/test01/__init__.py @@ -1 +0,0 @@ -# -*- coding: utf-8 -*- diff --git a/music21/musedata/translate.py b/music21/musedata/translate.py index 28b624078a..1b9826293d 100644 --- a/music21/musedata/translate.py +++ b/music21/musedata/translate.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: musedata.translate.py # Purpose: Translate MuseData into music21 objects diff --git a/music21/musicxml/__init__.py b/music21/musicxml/__init__.py index 731895b0ba..d4ba5d5fdf 100644 --- a/music21/musicxml/__init__.py +++ b/music21/musicxml/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: musicxml/__init__.py # Purpose: Access to musicxml library diff --git a/music21/musicxml/archiveTools.py b/music21/musicxml/archiveTools.py index 4840b5fc71..a996e8e975 100644 --- a/music21/musicxml/archiveTools.py +++ b/music21/musicxml/archiveTools.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Name: musicxml/archiveTools.py # Purpose: Tools for compressing and decompressing MusicXML files diff --git a/music21/musicxml/helpers.py b/music21/musicxml/helpers.py index 6c6135f127..b426a54214 100644 --- a/music21/musicxml/helpers.py +++ b/music21/musicxml/helpers.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: musicxml/helpers.py # Purpose: Helper routines for musicxml export diff --git a/music21/musicxml/lilypondTestSuite/__init__.py b/music21/musicxml/lilypondTestSuite/__init__.py index bde8883547..85b3ed0035 100644 --- a/music21/musicxml/lilypondTestSuite/__init__.py +++ b/music21/musicxml/lilypondTestSuite/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- ''' The Lilypond MusicXML Test Suite comes from https://github.com/cuthbertLab/musicxmlTestSuite diff --git a/music21/musicxml/m21ToXml.py b/music21/musicxml/m21ToXml.py index c2c47868eb..96d0caa972 100644 --- a/music21/musicxml/m21ToXml.py +++ b/music21/musicxml/m21ToXml.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: musicxml/m21ToXml.py # Purpose: Translate from music21 objects to musicxml representation diff --git a/music21/musicxml/partStaffExporter.py b/music21/musicxml/partStaffExporter.py index 6efb735436..abe52486a4 100644 --- a/music21/musicxml/partStaffExporter.py +++ b/music21/musicxml/partStaffExporter.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: musicxml/partStaffExporter.py # Purpose: Change music21 PartStaff objects to single musicxml parts diff --git a/music21/musicxml/testFiles.py b/music21/musicxml/testFiles.py index fe991e98fb..842c0f2a9e 100644 --- a/music21/musicxml/testFiles.py +++ b/music21/musicxml/testFiles.py @@ -1,5 +1,4 @@ -# -*- coding: utf-8 -*- -# ------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ # Name: testFiles.py # Purpose: MusicXML test files # diff --git a/music21/musicxml/testPrimitive.py b/music21/musicxml/testPrimitive.py index bee3baf4fa..1914116c8f 100644 --- a/music21/musicxml/testPrimitive.py +++ b/music21/musicxml/testPrimitive.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: testPrimitive.py # Purpose: MusicXML test files diff --git a/music21/musicxml/xmlObjects.py b/music21/musicxml/xmlObjects.py index 3d5049f86a..2342e50d8b 100644 --- a/music21/musicxml/xmlObjects.py +++ b/music21/musicxml/xmlObjects.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: musicxml/xmlObjects.py # Purpose: MusicXML objects for conversion to and from music21 diff --git a/music21/musicxml/xmlSoundParser.py b/music21/musicxml/xmlSoundParser.py index ff8c8aa62a..df9f47b94b 100644 --- a/music21/musicxml/xmlSoundParser.py +++ b/music21/musicxml/xmlSoundParser.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: musicxml/xmlSoundParser.py # Purpose: Translate the tag to music21 diff --git a/music21/musicxml/xmlToM21.py b/music21/musicxml/xmlToM21.py index 69c9bf9648..fee5e107dd 100644 --- a/music21/musicxml/xmlToM21.py +++ b/music21/musicxml/xmlToM21.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: musicxml/xmlToM21.py # Purpose: Conversion from MusicXML to Music21 diff --git a/music21/note.py b/music21/note.py index 887ef68488..7a56c69bf0 100644 --- a/music21/note.py +++ b/music21/note.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: note.py # Purpose: music21 classes for representing notes diff --git a/music21/noteworthy/__init__.py b/music21/noteworthy/__init__.py index 72cae6ac3a..50e1f0357a 100644 --- a/music21/noteworthy/__init__.py +++ b/music21/noteworthy/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: noteworthy/__init__.py # Purpose: parses NWCTXT Notation diff --git a/music21/noteworthy/binaryTranslate.py b/music21/noteworthy/binaryTranslate.py index 29bd804277..47ae916e44 100644 --- a/music21/noteworthy/binaryTranslate.py +++ b/music21/noteworthy/binaryTranslate.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: noteworthy/binaryTranslate.py # Purpose: parses .nwc binary files, compressed and uncompressed diff --git a/music21/noteworthy/translate.py b/music21/noteworthy/translate.py index d447350d62..7666fb8d45 100644 --- a/music21/noteworthy/translate.py +++ b/music21/noteworthy/translate.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: noteworthy/translate.py # Purpose: translates Noteworthy Composer's NWCTXT format diff --git a/music21/omr/__init__.py b/music21/omr/__init__.py index 38bb644a57..ff83626126 100644 --- a/music21/omr/__init__.py +++ b/music21/omr/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: omr/__init__.py # Purpose: music21 modules for improving and evaluating (not performing) OMR diff --git a/music21/omr/correctors.py b/music21/omr/correctors.py index 320704ced9..c6effb9263 100644 --- a/music21/omr/correctors.py +++ b/music21/omr/correctors.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: omr/correctors.py # Purpose: music21 modules for correcting the output from OMR software diff --git a/music21/omr/evaluators.py b/music21/omr/evaluators.py index a455147726..d1d79b377b 100644 --- a/music21/omr/evaluators.py +++ b/music21/omr/evaluators.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: omr/evaluators.py # Purpose: music21 module for evaluating correcting of output from OMR software diff --git a/music21/percussion.py b/music21/percussion.py index 9529361899..a799403432 100644 --- a/music21/percussion.py +++ b/music21/percussion.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: percussion.py # Purpose: music21 classes for representing unpitched events diff --git a/music21/pitch.py b/music21/pitch.py index 42a6c4cee2..065a4bcd00 100644 --- a/music21/pitch.py +++ b/music21/pitch.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: pitch.py # Purpose: music21 classes for representing pitches diff --git a/music21/prebase.py b/music21/prebase.py index b5e213ac53..18f8a2982d 100644 --- a/music21/prebase.py +++ b/music21/prebase.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: prebase.py # Purpose: classes for anything in music21 to inherit from. diff --git a/music21/repeat.py b/music21/repeat.py index 903207ab64..f0138c627d 100644 --- a/music21/repeat.py +++ b/music21/repeat.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: repeat.py # Purpose: Base classes for processing repeats diff --git a/music21/roman.py b/music21/roman.py index 407143fe9f..b8be71dead 100644 --- a/music21/roman.py +++ b/music21/roman.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Name: roman.py # Purpose: music21 classes for doing Roman Numeral / Tonal analysis diff --git a/music21/romanText/__init__.py b/music21/romanText/__init__.py index 78bed2c99a..91a652e2af 100644 --- a/music21/romanText/__init__.py +++ b/music21/romanText/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: romanText/__init__.py # Purpose: music21 classes for processing roman numeral analysis files diff --git a/music21/romanText/clercqTemperley.py b/music21/romanText/clercqTemperley.py index e4a3b99b77..222054003f 100644 --- a/music21/romanText/clercqTemperley.py +++ b/music21/romanText/clercqTemperley.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: clercqTemperley.py # Purpose: Routines to parse the popular music diff --git a/music21/romanText/rtObjects.py b/music21/romanText/rtObjects.py index 6f58ec7854..24a5c82d80 100644 --- a/music21/romanText/rtObjects.py +++ b/music21/romanText/rtObjects.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: romanText/rtObjects.py # Purpose: music21 objects for processing roman numeral analysis text files diff --git a/music21/romanText/testFiles.py b/music21/romanText/testFiles.py index 43baf1ff51..ed7e4d8f10 100644 --- a/music21/romanText/testFiles.py +++ b/music21/romanText/testFiles.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: romanText/base.py # Purpose: test files for roman numeral text analysis diff --git a/music21/romanText/translate.py b/music21/romanText/translate.py index 9bb2379a04..57f98ce00a 100644 --- a/music21/romanText/translate.py +++ b/music21/romanText/translate.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: romanText/translate.py # Purpose: Translation routines for roman numeral analysis text files diff --git a/music21/romanText/tsvConverter.py b/music21/romanText/tsvConverter.py index b1e7a962d9..bec9844517 100644 --- a/music21/romanText/tsvConverter.py +++ b/music21/romanText/tsvConverter.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: romanText/tsvConverter.py # Purpose: Converter for the DCMLab's tabular format for representing harmonic analysis. diff --git a/music21/romanText/writeRoman.py b/music21/romanText/writeRoman.py index 839eab2bca..431f36486b 100644 --- a/music21/romanText/writeRoman.py +++ b/music21/romanText/writeRoman.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: romanText/writeRoman.py # Purpose: Writer for the 'RomanText' format diff --git a/music21/scale/__init__.py b/music21/scale/__init__.py index a425f49c3d..80e81d0eaf 100644 --- a/music21/scale/__init__.py +++ b/music21/scale/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: scale.py # Purpose: music21 classes for representing scales diff --git a/music21/scale/intervalNetwork.py b/music21/scale/intervalNetwork.py index c79224ba0d..82a475b792 100644 --- a/music21/scale/intervalNetwork.py +++ b/music21/scale/intervalNetwork.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: scale.intervalNetwork.py # Purpose: A graph of intervals, for scales and harmonies. diff --git a/music21/scale/scala/__init__.py b/music21/scale/scala/__init__.py index 3e4d85f266..b07156cade 100644 --- a/music21/scale/scala/__init__.py +++ b/music21/scale/scala/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: scala/__init__.py # Purpose: Interface and representation of Scala scale files diff --git a/music21/scale/scala/scl/__init__.py b/music21/scale/scala/scl/__init__.py index 40a96afc6f..e69de29bb2 100644 --- a/music21/scale/scala/scl/__init__.py +++ b/music21/scale/scala/scl/__init__.py @@ -1 +0,0 @@ -# -*- coding: utf-8 -*- diff --git a/music21/scale/test_scale_main.py b/music21/scale/test_scale_main.py index df9e45bdde..b0b4cf5735 100644 --- a/music21/scale/test_scale_main.py +++ b/music21/scale/test_scale_main.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: scale.test_scale_main.py # Purpose: Tests for scale/__init__.py diff --git a/music21/search/__init__.py b/music21/search/__init__.py index 6d256f09a8..94ffddb2eb 100644 --- a/music21/search/__init__.py +++ b/music21/search/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: search/__init__.py # Purpose: music21 classes for searching within files diff --git a/music21/search/base.py b/music21/search/base.py index 3449ad3b61..0ddff09e88 100644 --- a/music21/search/base.py +++ b/music21/search/base.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: search/base.py # Purpose: music21 classes for searching within files diff --git a/music21/search/lyrics.py b/music21/search/lyrics.py index 32d7c673d6..a873e668b9 100644 --- a/music21/search/lyrics.py +++ b/music21/search/lyrics.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: search/lyrics.py # Purpose: music21 classes for searching lyrics diff --git a/music21/search/segment.py b/music21/search/segment.py index 6987f29899..e6f9158f26 100644 --- a/music21/search/segment.py +++ b/music21/search/segment.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: search/segment.py # Purpose: music21 classes for searching via segment matching diff --git a/music21/search/serial.py b/music21/search/serial.py index e59d374f03..5b61a577de 100644 --- a/music21/search/serial.py +++ b/music21/search/serial.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: search.serial.py # Purpose: music21 classes for serial searching diff --git a/music21/serial.py b/music21/serial.py index 741c718652..3ce2a86619 100644 --- a/music21/serial.py +++ b/music21/serial.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: serial.py # Purpose: music21 classes for serial transformations diff --git a/music21/sieve.py b/music21/sieve.py index f8066e0cd7..ec66a11e6c 100644 --- a/music21/sieve.py +++ b/music21/sieve.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: sieve.py # Purpose: sieve operations, after Iannis Xenakis. diff --git a/music21/sites.py b/music21/sites.py index cfcd1f542f..fc44ca46fc 100644 --- a/music21/sites.py +++ b/music21/sites.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: sites.py # Purpose: Objects for keeping track of relationships among Music21Objects diff --git a/music21/sorting.py b/music21/sorting.py index 7ada9a1281..ffc6dbd8e4 100644 --- a/music21/sorting.py +++ b/music21/sorting.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Name: sorting.py # Purpose: Music21 class for sorting diff --git a/music21/spanner.py b/music21/spanner.py index 9a1f64d163..a27efd7324 100644 --- a/music21/spanner.py +++ b/music21/spanner.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: spanner.py # Purpose: The Spanner base-class and subclasses diff --git a/music21/stream/__init__.py b/music21/stream/__init__.py index 9d86b16a1d..80c1715252 100644 --- a/music21/stream/__init__.py +++ b/music21/stream/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Name: stream/__init__.py # Purpose: base classes for dealing with groups of positioned objects diff --git a/music21/stream/base.py b/music21/stream/base.py index f62b3a04a1..33cfa587f9 100644 --- a/music21/stream/base.py +++ b/music21/stream/base.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Name: stream/base.py # Purpose: base classes for dealing with groups of positioned objects diff --git a/music21/stream/core.py b/music21/stream/core.py index b106fb97f3..0dc3019f5a 100644 --- a/music21/stream/core.py +++ b/music21/stream/core.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Name: stream/core.py # Purpose: mixin class for the core elements of Streams diff --git a/music21/stream/enums.py b/music21/stream/enums.py index 1088d95bde..52081bfe63 100644 --- a/music21/stream/enums.py +++ b/music21/stream/enums.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Name: stream/enums.py # Purpose: enumerations for streams diff --git a/music21/stream/filters.py b/music21/stream/filters.py index fdfce4f00a..296f3854f5 100644 --- a/music21/stream/filters.py +++ b/music21/stream/filters.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Name: stream/filters.py # Purpose: Classes for filtering iterators of streams diff --git a/music21/stream/iterator.py b/music21/stream/iterator.py index 1066ede0b2..5318f2291d 100644 --- a/music21/stream/iterator.py +++ b/music21/stream/iterator.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Name: stream/iterator.py # Purpose: Classes for walking through streams diff --git a/music21/stream/makeNotation.py b/music21/stream/makeNotation.py index cdcabf1518..693ae55f92 100644 --- a/music21/stream/makeNotation.py +++ b/music21/stream/makeNotation.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Name: makeNotation.py # Purpose: functionality for manipulating streams diff --git a/music21/stream/streamStatus.py b/music21/stream/streamStatus.py index 60e175d986..1830ec5cfc 100644 --- a/music21/stream/streamStatus.py +++ b/music21/stream/streamStatus.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Name: streamStatus.py # Purpose: Functionality for reporting on the notational status of streams diff --git a/music21/stream/tests.py b/music21/stream/tests.py index 5374e04c62..0de826fb5a 100644 --- a/music21/stream/tests.py +++ b/music21/stream/tests.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: stream/tests.py # Purpose: Tests for streams diff --git a/music21/stream/tools.py b/music21/stream/tools.py index 86f5c2844e..efd1f3fe6b 100644 --- a/music21/stream/tools.py +++ b/music21/stream/tools.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: stream/tools.py # Purpose: Additional tools for working with streams diff --git a/music21/style.py b/music21/style.py index a297a292df..2167a56681 100644 --- a/music21/style.py +++ b/music21/style.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Name: style.py # Purpose: Music21 classes for non-analytic display properties diff --git a/music21/tablature.py b/music21/tablature.py index 63a0ccf622..2c019b4252 100644 --- a/music21/tablature.py +++ b/music21/tablature.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: tablature.py # Purpose: Object for storing music21 information in the form of musical tablature. diff --git a/music21/tempo.py b/music21/tempo.py index ce6eae255e..3d51e260e7 100644 --- a/music21/tempo.py +++ b/music21/tempo.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: tempo.py # Purpose: Classes and tools relating to tempo diff --git a/music21/test/commonTest.py b/music21/test/commonTest.py index 1ca7ddfa31..b1922bd159 100644 --- a/music21/test/commonTest.py +++ b/music21/test/commonTest.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: commonTest.py # Purpose: Things common to testing diff --git a/music21/test/coverageM21.py b/music21/test/coverageM21.py index 9bf178fd1a..1fbe89f3a0 100644 --- a/music21/test/coverageM21.py +++ b/music21/test/coverageM21.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: coverageM21.py # Purpose: Starts Coverage w/ default arguments diff --git a/music21/test/memoryUsage.py b/music21/test/memoryUsage.py index dfb1b88042..1159cb7d11 100644 --- a/music21/test/memoryUsage.py +++ b/music21/test/memoryUsage.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import annotations from music21 import exceptions21 diff --git a/music21/test/multiprocessTest.py b/music21/test/multiprocessTest.py index 3d92a1c0b5..65804e9062 100644 --- a/music21/test/multiprocessTest.py +++ b/music21/test/multiprocessTest.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: multiprocesssTest.py # Purpose: Controller for all tests in music21 run concurrently. diff --git a/music21/test/testDefault.py b/music21/test/testDefault.py index 3cf43240a6..13bfe2a63f 100644 --- a/music21/test/testDefault.py +++ b/music21/test/testDefault.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: testDefault.py # Purpose: Controller for all tests in music21 in the default Environment. diff --git a/music21/test/testExternal.py b/music21/test/testExternal.py index 6292ed51c6..19ac47a78a 100644 --- a/music21/test/testExternal.py +++ b/music21/test/testExternal.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: testExternal.py # Purpose: Controller for all tests employing external software and diff --git a/music21/test/testLint.py b/music21/test/testLint.py index 522d1472d0..fdda175a65 100644 --- a/music21/test/testLint.py +++ b/music21/test/testLint.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: testLint.py # Purpose: Controller for all lint based testing. diff --git a/music21/test/testPerformance.py b/music21/test/testPerformance.py index cd161f6455..e4c3c6023b 100644 --- a/music21/test/testPerformance.py +++ b/music21/test/testPerformance.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: testPerformance.py # Purpose: Tests keep track of long-term performance targets diff --git a/music21/test/testRunner.py b/music21/test/testRunner.py index 335d48415e..519be56bc9 100644 --- a/music21/test/testRunner.py +++ b/music21/test/testRunner.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Name: testRunner.py # Purpose: Music21 testing suite diff --git a/music21/test/testSerialization.py b/music21/test/testSerialization.py index f7d9914863..4c6e1da140 100644 --- a/music21/test/testSerialization.py +++ b/music21/test/testSerialization.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: testSerialization.py # Purpose: tests for serializing music21 objects diff --git a/music21/test/testSingleCoreAll.py b/music21/test/testSingleCoreAll.py index c6ca26fc59..6fd06d6dda 100644 --- a/music21/test/testSingleCoreAll.py +++ b/music21/test/testSingleCoreAll.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: test.py # Purpose: Controller for all module tests in music21. diff --git a/music21/test/test_base.py b/music21/test/test_base.py index 436a474ae5..070a345567 100644 --- a/music21/test/test_base.py +++ b/music21/test/test_base.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: test.test_base.py # Purpose: music21 tests for Music21Objects etc. diff --git a/music21/test/test_metadata.py b/music21/test/test_metadata.py index ef8941a65e..3784dd4e36 100644 --- a/music21/test/test_metadata.py +++ b/music21/test/test_metadata.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import annotations import re diff --git a/music21/test/test_pitch.py b/music21/test/test_pitch.py index b6f9783a61..3e92d0479d 100644 --- a/music21/test/test_pitch.py +++ b/music21/test/test_pitch.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: test.test_pitch.py # Purpose: music21 tests for pitches diff --git a/music21/test/timeGraphImportStar.py b/music21/test/timeGraphImportStar.py index 4e6719d9f0..02216e26d1 100644 --- a/music21/test/timeGraphImportStar.py +++ b/music21/test/timeGraphImportStar.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: timeGraphsImportStar.py # Purpose: time how long it takes to import music21, and report biggest offenders diff --git a/music21/test/timeGraphs.py b/music21/test/timeGraphs.py index 6eda847dcb..1bd200356f 100644 --- a/music21/test/timeGraphs.py +++ b/music21/test/timeGraphs.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: timeGraphs.py # Purpose: time how long it takes to run music21 commands diff --git a/music21/test/toggleDebug.py b/music21/test/toggleDebug.py index 3a47b891ba..f8cd8b72f4 100644 --- a/music21/test/toggleDebug.py +++ b/music21/test/toggleDebug.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: test.toggleDebug.py # Purpose: Changes debug on if off, off if on diff --git a/music21/test/treeYield.py b/music21/test/treeYield.py index a6d297d041..39ea72fa70 100644 --- a/music21/test/treeYield.py +++ b/music21/test/treeYield.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: treeYield.py # Purpose: traverse a complex datastructure and yield elements diff --git a/music21/test/warningMultiprocessTest.py b/music21/test/warningMultiprocessTest.py index c01905639e..8fce5fdaec 100644 --- a/music21/test/warningMultiprocessTest.py +++ b/music21/test/warningMultiprocessTest.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- ''' Runs MultiprocessTest with all warnings including traceback ''' diff --git a/music21/text.py b/music21/text.py index a2e866c429..b3d443c1d9 100644 --- a/music21/text.py +++ b/music21/text.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: text.py # Purpose: music21 classes for text processing @@ -669,8 +668,8 @@ def testBasic(self): def testAssembleLyricsA(self): - from music21 import stream from music21 import note + from music21 import stream s = stream.Stream() for syl in ['hel-', '-lo', 'a-', '-gain']: n = note.Note() diff --git a/music21/tie.py b/music21/tie.py index f69afd462c..c1e6824764 100644 --- a/music21/tie.py +++ b/music21/tie.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: tie.py # Purpose: music21 classes for representing ties (visual and conceptual) diff --git a/music21/tinyNotation.py b/music21/tinyNotation.py index 6a5523e166..d2ffd3dd94 100644 --- a/music21/tinyNotation.py +++ b/music21/tinyNotation.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------- # Name: tinyNotation.py # Purpose: A simple notation input format. diff --git a/music21/tree/__init__.py b/music21/tree/__init__.py index 7a4058181b..edf8c211d3 100644 --- a/music21/tree/__init__.py +++ b/music21/tree/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Name: tree/__init__.py # Purpose: Tools for grouping notes and chords into a searchable tree diff --git a/music21/tree/analysis.py b/music21/tree/analysis.py index 0ad7674675..7ce5ebc62b 100644 --- a/music21/tree/analysis.py +++ b/music21/tree/analysis.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Name: tree/analysis.py # Purpose: horizontal analysis tools on timespan trees diff --git a/music21/tree/core.py b/music21/tree/core.py index 31a2f160cd..408c0e3e9f 100644 --- a/music21/tree/core.py +++ b/music21/tree/core.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Name: tree/core.py # Purpose: Core AVLTree object. To be optimized the hell out of. diff --git a/music21/tree/fromStream.py b/music21/tree/fromStream.py index 1995031c52..97e5cf10dd 100644 --- a/music21/tree/fromStream.py +++ b/music21/tree/fromStream.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Name: timespans/fromStream.py # Purpose: Tools for creating timespans from Streams diff --git a/music21/tree/node.py b/music21/tree/node.py index 9bfd64f405..c9f2d29480 100644 --- a/music21/tree/node.py +++ b/music21/tree/node.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Name: timespans/node.py # Purpose: Internal data structures for timespan collections diff --git a/music21/tree/spans.py b/music21/tree/spans.py index db5d02a59c..1571399d76 100644 --- a/music21/tree/spans.py +++ b/music21/tree/spans.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Name: tree/spans.py # Purpose: Tools for marking off spans of time that optionally contain diff --git a/music21/tree/timespanTree.py b/music21/tree/timespanTree.py index 0dcbfa9836..0065a3f784 100644 --- a/music21/tree/timespanTree.py +++ b/music21/tree/timespanTree.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Name: tree/timespanTree.py # Purpose: Subclasses of tree.trees.OffsetTree for manipulation @@ -814,9 +813,9 @@ def element(self, expr): class Test(unittest.TestCase): def testGetVerticalityAtWithKey(self): - from music21 import stream from music21 import key from music21 import note + from music21 import stream s = stream.Stream() s.insert(0, key.Key('C')) s.insert(0, note.Note('F#4')) diff --git a/music21/tree/toStream.py b/music21/tree/toStream.py index 797827edcc..38d617f996 100644 --- a/music21/tree/toStream.py +++ b/music21/tree/toStream.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Name: tree/toStream.py # Purpose: Tools for recreating streams from trees diff --git a/music21/tree/trees.py b/music21/tree/trees.py index 6fd8ab289c..07a8f04f89 100644 --- a/music21/tree/trees.py +++ b/music21/tree/trees.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Name: tree/trees.py # Purpose: Subclasses of tree.core.AVLTree for different purposes @@ -1482,8 +1481,8 @@ def testGetPositionAfterOffset(self): test that get position after works with an offset when the tree is built on SortTuples. ''' - from music21 import stream from music21 import note + from music21 import stream et = ElementTree() diff --git a/music21/tree/verticality.py b/music21/tree/verticality.py index 1ee2676fef..1b318d264d 100644 --- a/music21/tree/verticality.py +++ b/music21/tree/verticality.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ---------------------------------------------------------------------------- # Name: tree/verticality.py # Purpose: Object for dealing with vertical simultaneities in a diff --git a/music21/variant.py b/music21/variant.py index 5d963b152b..78bd8f9ff3 100644 --- a/music21/variant.py +++ b/music21/variant.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: variant.py # Purpose: Ossia and other variant reading tools diff --git a/music21/vexflow/__init__.py b/music21/vexflow/__init__.py index 0fc663b9be..6987fe9a9f 100644 --- a/music21/vexflow/__init__.py +++ b/music21/vexflow/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: vexflow/__init__.py # Purpose: music21 classes for converting music21 objects to vexflow diff --git a/music21/vexflow/toMusic21j.py b/music21/vexflow/toMusic21j.py index 479f025fa7..62ad8775bc 100644 --- a/music21/vexflow/toMusic21j.py +++ b/music21/vexflow/toMusic21j.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: vexflow/toMusic21j.py # Purpose: music21 classes for converting music21 objects to music21j diff --git a/music21/voiceLeading.py b/music21/voiceLeading.py index 46a39cdd88..95d3787ebc 100644 --- a/music21/voiceLeading.py +++ b/music21/voiceLeading.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: voiceLeading.py # Purpose: music21 classes for voice leading diff --git a/music21/volpiano.py b/music21/volpiano.py index e9063fbc6b..a59b9d9dcf 100644 --- a/music21/volpiano.py +++ b/music21/volpiano.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: volpiano.py # Purpose: music21 classes for converting to and from volpiano diff --git a/music21/volume.py b/music21/volume.py index 2b3a83d5ac..1b45fb3157 100644 --- a/music21/volume.py +++ b/music21/volume.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # Name: volume.py # Purpose: Objects for representing volume, amplitude, and related From c36ad90db6a4605547c6e330db9d4c9a46326502 Mon Sep 17 00:00:00 2001 From: Michael Scott Asato Cuthbert Date: Fri, 2 Jan 2026 15:16:04 -1000 Subject: [PATCH 02/13] Ruff E, Q fixed Plus spelling of "vice versa" --- music21/abcFormat/__init__.py | 53 ++++++++++++++++--------------- music21/analysis/reduction.py | 6 ++-- music21/audioSearch/__init__.py | 2 +- music21/base.py | 12 +++---- music21/chord/__init__.py | 4 +-- music21/clef.py | 2 +- music21/figuredBass/notation.py | 6 ++-- music21/humdrum/__init__.py | 2 -- music21/humdrum/instruments.py | 10 +++--- music21/interval.py | 4 +-- music21/lily/translate.py | 2 +- music21/midi/base.py | 2 +- music21/midi/tests.py | 4 +-- music21/musicxml/test_m21ToXml.py | 8 ++--- music21/musicxml/xmlToM21.py | 2 +- music21/pitch.py | 4 +-- music21/roman.py | 2 +- music21/romanText/rtObjects.py | 4 +-- music21/romanText/translate.py | 2 +- music21/romanText/tsvConverter.py | 8 ++--- music21/sites.py | 6 ++-- music21/spanner.py | 6 ++-- music21/stream/base.py | 8 ++--- music21/stream/tests.py | 22 ++++++------- music21/style.py | 10 +++--- music21/test/treeYield.py | 2 +- music21/variant.py | 9 +++--- music21/volume.py | 17 ++++++---- pyproject.toml | 41 ++++++++++++++++++++++++ 29 files changed, 154 insertions(+), 106 deletions(-) diff --git a/music21/abcFormat/__init__.py b/music21/abcFormat/__init__.py index 8dd819b911..bf279c8fde 100644 --- a/music21/abcFormat/__init__.py +++ b/music21/abcFormat/__init__.py @@ -3671,21 +3671,22 @@ def testSplitByMeasure(self): ah.process(testFiles.hectorTheHero) ahm = ah.splitByMeasure() - for i, l, r in [(0, None, None), # metadata - (2, '|:', '|'), - (3, '|', '|'), - (-2, '[1', ':|'), - (-1, '[2', '|'), - ]: - if l is None: + for i, left, right in [ + (0, None, None), # metadata + (2, '|:', '|'), + (3, '|', '|'), + (-2, '[1', ':|'), + (-1, '[2', '|'), + ]: + if left is None: self.assertEqual(ahm[i].leftBarToken, None) else: - self.assertEqual(ahm[i].leftBarToken.src, l) + self.assertEqual(ahm[i].leftBarToken.src, left) - if r is None: + if right is None: self.assertEqual(ahm[i].rightBarToken, None) else: - self.assertEqual(ahm[i].rightBarToken.src, r) + self.assertEqual(ahm[i].rightBarToken.src, right) # for ahSub in ah.splitByMeasure(): # environLocal.printDebug(['split by measure:', ahSub.tokens]) @@ -3696,37 +3697,39 @@ def testSplitByMeasure(self): ah.process(testFiles.theBeggerBoy) ahm = ah.splitByMeasure() - for i, l, r in [(0, None, None), # metadata - (1, None, '|'), - (-1, '||', None), # trailing lyric metadata - ]: - if l is None: + for i, left, right in [ + (0, None, None), # metadata + (1, None, '|'), + (-1, '||', None), # trailing lyric metadata + ]: + if left is None: self.assertEqual(ahm[i].leftBarToken, None) else: - self.assertEqual(ahm[i].leftBarToken.src, l) + self.assertEqual(ahm[i].leftBarToken.src, left) - if r is None: + if right is None: self.assertEqual(ahm[i].rightBarToken, None) else: - self.assertEqual(ahm[i].rightBarToken.src, r) + self.assertEqual(ahm[i].rightBarToken.src, right) # test a simple string with no bars ah = ABCHandler() ah.process('M:6/8\nL:1/8\nK:G\nc1D2') ahm = ah.splitByMeasure() - for i, l, r in [(0, None, None), # metadata - (-1, None, None), # note data, but no bars - ]: - if l is None: + for i, left, right in [ + (0, None, None), # metadata + (-1, None, None), # note data, but no bars + ]: + if left is None: self.assertEqual(ahm[i].leftBarToken, None) else: - self.assertEqual(ahm[i].leftBarToken.src, l) + self.assertEqual(ahm[i].leftBarToken.src, left) - if r is None: + if right is None: self.assertEqual(ahm[i].rightBarToken, None) else: - self.assertEqual(ahm[i].rightBarToken.src, r) + self.assertEqual(ahm[i].rightBarToken.src, right) def testMergeLeadingMetaData(self): from music21.abcFormat import testFiles diff --git a/music21/analysis/reduction.py b/music21/analysis/reduction.py index 7698032eab..58807b9f04 100644 --- a/music21/analysis/reduction.py +++ b/music21/analysis/reduction.py @@ -295,13 +295,13 @@ def _extractNoteReductiveEvent(self, n, infoDict=None, removeAfterParsing=True): # a list of Lyric objects - for k, l in enumerate(n.lyrics): + for k, lyr in enumerate(n.lyrics): # store measure index - rn = ReductiveNote(l.text, n, infoDict['measureIndex'], offset) + rn = ReductiveNote(lyr.text, n, infoDict['measureIndex'], offset) if rn.isParsed(): # environLocal.printDebug(['parsing reductive note', rn]) # use id, lyric text as hash - key = str(id(n)) + l.text + key = str(id(n)) + lyr.text self._reductiveNotes[key] = rn removalIndices.append(k) if removeAfterParsing: diff --git a/music21/audioSearch/__init__.py b/music21/audioSearch/__init__.py index f056fd391b..6732e89321 100644 --- a/music21/audioSearch/__init__.py +++ b/music21/audioSearch/__init__.py @@ -276,7 +276,7 @@ def normalizeInputFrequency(inputPitchFrequency, thresholds=None, pitches=None): ): raise AudioSearchException( 'Cannot normalize input frequency if thresholds are given and ' - + 'pitches are not, or vice-versa') + + 'pitches are not, or vice versa') if thresholds is None: (thresholds, pitches) = prepareThresholds() diff --git a/music21/base.py b/music21/base.py index 5a1acb8019..8f6b3599ba 100644 --- a/music21/base.py +++ b/music21/base.py @@ -749,8 +749,8 @@ def hasEditorialInformation(self) -> bool: >>> mObj.hasEditorialInformation True ''' - # anytime something is changed here, change in style.StyleMixin and vice-versa - return not (self._editorial is None) + # any time something is changed here, change in style.StyleMixin and vice versa + return self._editorial is not None @property def editorial(self) -> Editorial: @@ -772,7 +772,7 @@ def editorial(self) -> Editorial: # Dev note: because the property "editorial" shadows module editorial, # typing has to be in quotes. - # anytime something is changed here, change in style.StyleMixin and vice-versa + # anytime something is changed here, change in style.StyleMixin and vice versa if self._editorial is None: self._editorial = Editorial() return self._editorial @@ -800,8 +800,8 @@ def hasStyleInformation(self) -> bool: >>> mObj.hasStyleInformation True ''' - # anytime something is changed here, change in style.StyleMixin and vice-versa - return not (self._style is None) + # anytime something is changed here, change in style.StyleMixin and vice versa + return self._style is not None @property def style(self) -> Style: @@ -826,7 +826,7 @@ def style(self) -> Style: >>> n.style.absoluteX is None True ''' - # anytime something is changed here, change in style.StyleMixin and vice-versa + # anytime something is changed here, change in style.StyleMixin and vice versa if not self.hasStyleInformation: StyleClass = self._styleClass self._style = StyleClass() diff --git a/music21/chord/__init__.py b/music21/chord/__init__.py index 376bc9225d..5d6da18584 100644 --- a/music21/chord/__init__.py +++ b/music21/chord/__init__.py @@ -849,8 +849,8 @@ def __getitem__(self, key: int|str|note.Note|pitch.Pitch): if isinstance(key, int): try: foundNote = self._notes[key] # must be a number - except (KeyError, IndexError): - raise KeyError(keyErrorStr) + except (KeyError, IndexError) as exc: + raise KeyError(keyErrorStr) from exc elif isinstance(key, str): key = key.upper() diff --git a/music21/clef.py b/music21/clef.py index 01c442c3c6..2bbe5c9626 100644 --- a/music21/clef.py +++ b/music21/clef.py @@ -297,7 +297,7 @@ def octaveChange(self) -> int: >>> clef.Treble8vbClef().octaveChange -1 - Changing octaveChange changes lowestLine (but not vice-versa) + Changing octaveChange changes lowestLine (but not vice versa) >>> tc.lowestLine 31 diff --git a/music21/figuredBass/notation.py b/music21/figuredBass/notation.py index fe8099ec31..0ff137f8ac 100644 --- a/music21/figuredBass/notation.py +++ b/music21/figuredBass/notation.py @@ -771,8 +771,10 @@ def convertToPitch(pitchString): if isinstance(pitchString, str): try: return pitch.Pitch(pitchString) - except: - raise ValueError('Cannot convert string ' + pitchString + ' to a music21 Pitch.') + except (ValueError, pitch.PitchException) as pe: + raise ValueError( + 'Cannot convert string ' + pitchString + ' to a music21 Pitch.' + ) from pe raise TypeError('Cannot convert ' + pitchString + ' to a music21 Pitch.') diff --git a/music21/humdrum/__init__.py b/music21/humdrum/__init__.py index 9bd6a2dc39..28bdfe67e4 100644 --- a/music21/humdrum/__init__.py +++ b/music21/humdrum/__init__.py @@ -14,10 +14,8 @@ people who have previously used humdrum or need to import humdrum data (in spines, etc.) into music21. - Humdrum programs and their closest music21 equivalents: - ============ ================================================= ========================================================================================================================================================================= Humdrum music21 notes ============ ================================================= ========================================================================================================================================================================= diff --git a/music21/humdrum/instruments.py b/music21/humdrum/instruments.py index 6136f44850..4f0e893891 100644 --- a/music21/humdrum/instruments.py +++ b/music21/humdrum/instruments.py @@ -241,9 +241,10 @@ def fromHumdrumClass(hdClass): i = humdrumInstrumentClassToInstrument[hdClass] iObj = getattr(instrument, i)() return iObj - except: + except (IndexError, KeyError, AttributeError) as exc: raise HumdrumInstrumentException( - f'Cannot get an instrument from this humdrum class *IC{hdClass}') + f'Cannot get an instrument from this humdrum class *IC{hdClass}' + ) from exc def fromHumdrumInstrument(hdInst): @@ -259,9 +260,10 @@ def fromHumdrumInstrument(hdInst): i = humdrumInstruments[hdInst] iObj = getattr(instrument, i)() return iObj - except: + except (IndexError, KeyError, AttributeError) as exc: raise HumdrumInstrumentException( - f'Cannot get an instrument from this humdrum class: *I{hdInst}') + f'Cannot get an instrument from this humdrum class: *I{hdInst}' + ) from exc class Test(unittest.TestCase): diff --git a/music21/interval.py b/music21/interval.py index 5864145bb5..c5ab5a293c 100644 --- a/music21/interval.py +++ b/music21/interval.py @@ -1281,7 +1281,7 @@ def mod7inversion(self) -> int: ''' Return the inversion of this interval within an octave. For instance, seconds become sevenths, octaves become unisons, - and vice-versa. + and vice versa. All are undirected intervals. @@ -2083,7 +2083,7 @@ def reverse(self) -> DiatonicInterval: 'A-5' (Ascending) Augmented Unisons reverse to (Descending) - Diminished Unisons and vice-versa + Diminished Unisons and vice versa >>> aug1 = interval.DiatonicInterval('augmented', 1) >>> aug1.direction diff --git a/music21/lily/translate.py b/music21/lily/translate.py index 4e8c23745e..095ea7bc4b 100644 --- a/music21/lily/translate.py +++ b/music21/lily/translate.py @@ -597,7 +597,7 @@ def getLySpacersFromStream(self, streamIn, measuresOnly=True): dur = str(self.lyMultipliedDurationFromDuration(el.duration)) returnString = returnString + 's' + dur # general exception is the only way to catch str exceptions - except: # pylint: disable=bare-except + except Exception: for c in el.duration.components: dur = str(self.lyMultipliedDurationFromDuration(c)) returnString = returnString + 's' + dur diff --git a/music21/midi/base.py b/music21/midi/base.py index 3b14b3f5b8..7721b09b8e 100644 --- a/music21/midi/base.py +++ b/music21/midi/base.py @@ -13,7 +13,7 @@ ''' Objects and tools for processing MIDI data. Converts from MIDI files to :class:`~music21.midi.MidiEvent`, :class:`~music21.midi.MidiTrack`, and -:class:`~music21.midi.MidiFile` objects, and vice-versa. +:class:`~music21.midi.MidiFile` objects, and vice versa. This module originally used routines from Will Ware's public domain midi.py library from 2001 which was once posted at diff --git a/music21/midi/tests.py b/music21/midi/tests.py index 554f315d99..95363e9f99 100644 --- a/music21/midi/tests.py +++ b/music21/midi/tests.py @@ -1564,8 +1564,8 @@ def testMidiImportLyrics(self): for filename, encoding, lyricFact in testCases: fp = common.getSourceFilePath() / 'midi' / 'testPrimitive' / filename s = converter.parse(fp, encoding=encoding) - for (n, l) in zip(s.flatten().notes, lyricFact): - self.assertEqual(n.lyric, l) + for (n, lyricStr) in zip(s.flatten().notes, lyricFact): + self.assertEqual(n.lyric, lyricStr) def testMidiExportLyrics(self): lyricEn = 'cat' # ascii characters should be supported by every encoding diff --git a/music21/musicxml/test_m21ToXml.py b/music21/musicxml/test_m21ToXml.py index 545c476d27..5feb1ce275 100644 --- a/music21/musicxml/test_m21ToXml.py +++ b/music21/musicxml/test_m21ToXml.py @@ -1131,12 +1131,12 @@ def testSimple(self): with io.open(fp, encoding='utf-8') as f: v2 = f.read() differ = list(difflib.ndiff(v.splitlines(), v2.splitlines())) - for i, l in enumerate(differ): - if l.startswith('-') or l.startswith('?') or l.startswith('+'): - if 'id=' in l: + for i, line in enumerate(differ): + if line.startswith('-') or line.startswith('?') or line.startswith('+'): + if 'id=' in line: continue if self.show: - print(l) + print(line) # for j in range(i - 1,i + 1): # print(differ[j]) # print('------------------') diff --git a/music21/musicxml/xmlToM21.py b/music21/musicxml/xmlToM21.py index fee5e107dd..629faa7b89 100644 --- a/music21/musicxml/xmlToM21.py +++ b/music21/musicxml/xmlToM21.py @@ -2732,7 +2732,7 @@ def hasSystemLayout(): addPageLayout = hasPageLayout() addSystemLayout = hasSystemLayout() - addStaffLayout = not (mxPrint.find('staff-layout') is None) + addStaffLayout = mxPrint.find('staff-layout') is not None # --- now we know what we need to add, add em m = self.stream diff --git a/music21/pitch.py b/music21/pitch.py index 065a4bcd00..5d6231bb3e 100644 --- a/music21/pitch.py +++ b/music21/pitch.py @@ -2912,8 +2912,8 @@ def nameWithOctave(self, value: str): octave = int(value[-1]) self.name = name self.octave = octave - except: - raise PitchException(f'Cannot set a nameWithOctave with {value!r}') + except (ValueError, PitchException) as e: + raise PitchException(f'Cannot set a nameWithOctave with {value!r}') from e @property def unicodeNameWithOctave(self) -> str: diff --git a/music21/roman.py b/music21/roman.py index b8be71dead..3bb53e3162 100644 --- a/music21/roman.py +++ b/music21/roman.py @@ -3469,7 +3469,7 @@ def key(self, keyOrScale): # environLocal.printDebug(['got keyOrScale', keyOrScale]) try: keyClasses = keyOrScale.classes - except: # pragma: no cover + except AttributeError: # pragma: no cover raise RomanNumeralException( 'Cannot call classes on object {0!r}, send only Key ' 'or Scale Music21Objects'.format(keyOrScale)) diff --git a/music21/romanText/rtObjects.py b/music21/romanText/rtObjects.py index 24a5c82d80..06a79eac54 100644 --- a/music21/romanText/rtObjects.py +++ b/music21/romanText/rtObjects.py @@ -1110,8 +1110,8 @@ def splitAtHeader(self, lines): ''' # iterate over lines and find the first measure definition iStartBody = None - for i, l in enumerate(lines): - if reMeasureTag.match(l.strip()) is not None: + for i, line in enumerate(lines): + if reMeasureTag.match(line.strip()) is not None: # found a measure definition iStartBody = i break diff --git a/music21/romanText/translate.py b/music21/romanText/translate.py index 57f98ce00a..dc858b10a4 100644 --- a/music21/romanText/translate.py +++ b/music21/romanText/translate.py @@ -932,7 +932,7 @@ def setAnalyticKey(self, a): try: # this sets the key and the keysignature self.kCurrent, pl = _getKeyAndPrefix(a) self.prefixLyric += pl - except: # pragma: no cover + except (ValueError, exceptions21.Music21Exception): # pragma: no cover raise RomanTextTranslateException( f'cannot get analytic key from {a.src} in line {self.currentMeasureToken.src}') self.setKeyChangeToken = True diff --git a/music21/romanText/tsvConverter.py b/music21/romanText/tsvConverter.py index bec9844517..814446122d 100644 --- a/music21/romanText/tsvConverter.py +++ b/music21/romanText/tsvConverter.py @@ -888,17 +888,17 @@ def _m21ToTsv_v2(self) -> list[list[str]]: thisEntry.numeral = thisRN.romanNumeral thisEntry.form = getForm(thisRN) # Strip any leading non-digits from figbass (e.g., M43 -> 43) - figbassm = re.match(r'^\D*(\d.*|)', thisRN.figuresWritten) + fig_bass_m = re.match(r'^\D*(\d.*|)', thisRN.figuresWritten) # implementing the following check according to the review - # at https://github.com/cuthbertLab/music21/pull/1267/files/a1ad510356697f393bf6b636af8f45e81ad6ccc8#r936472302 #pylint: disable=line-too-long + # at https://github.com/cuthbertLab/music21/pull/1267/ # but the match should always exist because either: # 1. there is a digit in the string, in which case it matches # because of the left side of the alternation operator # 2. there is no digit in the string, in which case it matches # because of the right side of the alternation operator # (an empty string) - if figbassm is not None: - thisEntry.figbass = figbassm.group(1) + if fig_bass_m is not None: + thisEntry.figbass = fig_bass_m.group(1) else: thisEntry.figbass = '' thisEntry.changes = None diff --git a/music21/sites.py b/music21/sites.py index fc44ca46fc..309cfe37a1 100644 --- a/music21/sites.py +++ b/music21/sites.py @@ -396,7 +396,7 @@ def clear(self): def yieldSites(self, *, excludeNone: t.Literal[True], - sortByCreationTime: t.Union[bool, t.Literal['reverse']] = False, + sortByCreationTime: bool|t.Literal['reverse'] = False, priorityTarget=None, ) -> Generator[stream.Stream, None, None]: ... @@ -405,7 +405,7 @@ def yieldSites(self, def yieldSites(self, *, excludeNone: bool = False, - sortByCreationTime: t.Union[bool, t.Literal['reverse']] = False, + sortByCreationTime: bool|t.Literal['reverse'] = False, priorityTarget=None, ) -> Generator[stream.Stream|None, None, None]: ... @@ -413,7 +413,7 @@ def yieldSites(self, def yieldSites(self, *, excludeNone: bool = False, - sortByCreationTime: t.Union[bool, t.Literal['reverse']] = False, + sortByCreationTime: bool|t.Literal['reverse'] = False, priorityTarget=None, ) -> Generator[stream.Stream|None, None, None]: # noinspection PyDunderSlots diff --git a/music21/spanner.py b/music21/spanner.py index a27efd7324..d7e8afe030 100644 --- a/music21/spanner.py +++ b/music21/spanner.py @@ -207,8 +207,7 @@ class Spanner(base.Music21Object): equalityAttributes = ('spannerStorage',) def __init__(self, - *spannedElements: t.Union[base.Music21Object, - Sequence[base.Music21Object]], + *spannedElements: base.Music21Object|Sequence[base.Music21Object], **keywords): super().__init__(**keywords) @@ -424,8 +423,7 @@ def getSpannedElementIds(self): def addSpannedElements( self, - spannedElements: t.Union[Sequence[base.Music21Object], - base.Music21Object], + spannedElements: Sequence[base.Music21Object]|base.Music21Object, *otherElements: base.Music21Object, ): ''' diff --git a/music21/stream/base.py b/music21/stream/base.py index 33cfa587f9..c942b79776 100644 --- a/music21/stream/base.py +++ b/music21/stream/base.py @@ -2957,7 +2957,7 @@ def replace(self, Note that it does not work the other way: if we made the replacement on `s` then `sf`, the flattened representation, would not be changed, since `s` - does not derive from `sf` but vice-versa. + does not derive from `sf` but vice versa. With `recurse=True`, a stream can replace an element that is further down in the hierarchy. First let's set up a @@ -8978,7 +8978,7 @@ def beatAndMeasureFromOffset(self, searchOffset, fixZeros=True): 'beatAndMeasureFromOffset: could not find a time signature for that place.') try: myBeat = ts1.getBeatProportion(searchOffset - myMeas.offset) - except: + except (ValueError, IndexError, AttributeError, exceptions21.Music21Exception): raise StreamException( 'beatAndMeasureFromOffset: offset is beyond the end of the piece') foundMeasureNumber = myMeas.number @@ -12830,7 +12830,7 @@ def showVariantAsOssialikePart(self, containedPart, variantGroups, *, inPlace=Fa from music21 import variant # containedPart must be in self, or an exception is raised. - if not (containedPart in self): + if containedPart not in self: raise variant.VariantException(f'Could not find {containedPart} in {self}') if inPlace is True: @@ -12853,7 +12853,7 @@ def showVariantAsOssialikePart(self, containedPart, variantGroups, *, inPlace=Fa eClasses = e.classes if 'Variant' in eClasses: elementGroups = e.groups - if (not (variantGroup in elementGroups) + if (variantGroup not in elementGroups or e.lengthType in ['elongation', 'deletion']): newPart.remove(e) else: diff --git a/music21/stream/tests.py b/music21/stream/tests.py index 0de826fb5a..725ec6e14c 100644 --- a/music21/stream/tests.py +++ b/music21/stream/tests.py @@ -7958,23 +7958,23 @@ def getS(): return ss s = getS() - l, r = s.splitAtQuarterLength(2, retainOrigin=True) - # if retain origin is true, l is the original - self.assertIs(l, s) - self.assertEqual(l.highestTime, 2) - self.assertEqual(len(l.notes), 2) - self.assertEqual(r.highestTime, 2) - self.assertEqual(len(r.notes), 2) + left, right = s.splitAtQuarterLength(2, retainOrigin=True) + # if retain origin is true, left is the original + self.assertIs(left, s) + self.assertEqual(left.highestTime, 2) + self.assertEqual(len(left.notes), 2) + self.assertEqual(right.highestTime, 2) + self.assertEqual(len(right.notes), 2) sPost = Stream() - sPost.append(l) - sPost.append(r) + sPost.append(left) + sPost.append(right) s = getS() l2, r2 = s.splitAtQuarterLength(2, retainOrigin=False) self.assertIsNot(l2, s) - self.assertEqual(l2.highestTime, l.highestTime) - self.assertEqual(len(l2), len(l)) + self.assertEqual(l2.highestTime, left.highestTime) + self.assertEqual(len(l2), len(left)) self.assertEqual(len(r2.notes), 2) s = getS() diff --git a/music21/style.py b/music21/style.py index 2167a56681..a558df407f 100644 --- a/music21/style.py +++ b/music21/style.py @@ -623,7 +623,7 @@ class StyleMixin(common.SlottedObjectMixin): Not used by Music21Objects because of the added trouble in copying etc. so there is code duplication with base.Music21Object ''' - # anytime something is changed here, change in base.Music21Object and vice-versa + # anytime something is changed here, change in base.Music21Object and vice versa _styleClass = Style __slots__ = ('_style', '_editorial') @@ -658,7 +658,7 @@ def hasStyleInformation(self) -> bool: except AttributeError: pass - return not (self._style is None) + return self._style is not None @property def style(self) -> Style: @@ -683,7 +683,7 @@ def style(self) -> Style: >>> acc.style.absoluteX is None True ''' - # anytime something is changed here, change in base.Music21Object and vice-versa + # anytime something is changed here, change in base.Music21Object and vice versa if self._style is None: styleClass = self._styleClass self._style = styleClass() @@ -712,7 +712,7 @@ def hasEditorialInformation(self) -> bool: >>> acc.hasEditorialInformation True ''' - return not (self._editorial is None) + return self._editorial is not None @property def editorial(self) -> editorial.Editorial: @@ -731,7 +731,7 @@ def editorial(self) -> editorial.Editorial: >>> acc.editorial }> ''' - # anytime something is changed here, change in base.Music21Object and vice-versa + # anytime something is changed here, change in base.Music21Object and vice versa from music21 import editorial if self._editorial is None: self._editorial = editorial.Editorial() diff --git a/music21/test/treeYield.py b/music21/test/treeYield.py index 39ea72fa70..b24691360b 100644 --- a/music21/test/treeYield.py +++ b/music21/test/treeYield.py @@ -60,7 +60,7 @@ def run(self, obj, memo=None): tObj = type(obj) if tObj in self.nonIterables: pass - elif tObj == dict: + elif tObj is dict: for keyX in obj: dictTuple = ('dict', keyX) self.stackVals.append(dictTuple) diff --git a/music21/variant.py b/music21/variant.py index 78bd8f9ff3..1ac59377ad 100644 --- a/music21/variant.py +++ b/music21/variant.py @@ -24,7 +24,6 @@ from collections.abc import Sequence import copy import difflib -import typing as t import unittest from music21 import base @@ -93,9 +92,11 @@ class Variant(base.Music21Object): # this copies the init of Streams def __init__( self, - givenElements: t.Union[None, - base.Music21Object, - Sequence[base.Music21Object]] = None, + givenElements: ( + None + | base.Music21Object + | Sequence[base.Music21Object] + ) = None, name: str|None = None, givenElementsBehavior: GivenElementsBehavior = GivenElementsBehavior.OFFSETS, **music21ObjectKeywords, diff --git a/music21/volume.py b/music21/volume.py index 1b45fb3157..f1415df45a 100644 --- a/music21/volume.py +++ b/music21/volume.py @@ -141,10 +141,11 @@ def mergeAttributes(self, other): def getRealizedStr(self, useDynamicContext: dynamics.Dynamic|bool = True, useVelocity=True, - useArticulations: t.Union[bool, - articulations.Articulation, - Iterable[articulations.Articulation] - ] = True, + useArticulations: ( + bool + | articulations.Articulation + | Iterable[articulations.Articulation] + ) = True, baseLevel=0.5, clip=True): ''' @@ -165,9 +166,11 @@ def getRealized( self, useDynamicContext: bool|dynamics.Dynamic = True, useVelocity=True, - useArticulations: t.Union[ - bool, articulations.Articulation, Iterable[articulations.Articulation] - ] = True, + useArticulations: ( + bool + | articulations.Articulation + | Iterable[articulations.Articulation] + ) = True, baseLevel=0.5, clip=True, ): diff --git a/pyproject.toml b/pyproject.toml index d16731c5fb..46e692cf6c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -70,3 +70,44 @@ include = [ "music21", "py.typed", # indicates source is typed. ] + +[tool.ruff] +line-length = 100 + +[tool.ruff.lint] +# Flake8 core (pycodestyle + pyflakes) + flake8-quotes +select = ['E', 'Q'] + +# add once allowed: E122 (continuation line missing indentation) and E124 (bracket align) + +ignore = [ + # space around | -- nice to omit in int|str + 'E227', + # 0 blank lines -- good test but something going wrong in new algorithm + 'E301', + # blank lines + 'E302', + # blank lines + 'E303', + # do not assign lambda -- okay by me. + 'E731', +] + +[tool.ruff.lint.per-file-ignores] +'music21/abcFormat/testFiles.py' = ['E501'] # line-too-long +# when allowed again -- chord/tables omit E122, E127 +'music21/chord/tables.py' = ['E201', 'E202', 'E203', 'E221', 'E231', 'E241'] +'music21/common/__init__.py' = ['F403'] +'music21/features/__init__.py' = ['F403'] +'music21/humdrum/__init__.py' = ['E501'] # line-too-long +'music21/humdrum/testFiles.py' = ['E501'] # line-too-long +'music21/musicxml/testFiles.py' = ['E501'] # line-too-long +'music21/musicxml/testPrimitive.py' = ['E501'] # line-too-long +'music21/romanText/testFiles.py' = ['E501'] # line-too-long +'music21/search/__init__.py' = ['F403'] +'music21/variant.py' = ['E501'] # line-too-long + +[tool.ruff.lint.flake8-quotes] +inline-quotes = 'single' +multiline-quotes = 'single' +docstring-quotes = 'single' From 0e47bfd2aabd004d5d987f77b65a45d3c2768c49 Mon Sep 17 00:00:00 2001 From: Michael Scott Asato Cuthbert Date: Fri, 2 Jan 2026 15:31:11 -1000 Subject: [PATCH 03/13] Add F tests --- music21/__init__.py | 10 ++++++++++ music21/common/__init__.py | 13 +++++++++++++ music21/corpus/__init__.py | 2 +- music21/figuredBass/realizer.py | 3 --- music21/metadata/__init__.py | 5 ----- music21/test/__init__.py | 12 ++++++++++++ music21/test/commonTest.py | 5 ++--- music21/test/coverageM21.py | 2 +- music21/tree/trees.py | 2 -- pyproject.toml | 6 ++++-- 10 files changed, 43 insertions(+), 17 deletions(-) diff --git a/music21/__init__.py b/music21/__init__.py index 351446b07c..7cbd1faa5c 100644 --- a/music21/__init__.py +++ b/music21/__init__.py @@ -167,6 +167,16 @@ 'voiceLeading', 'volpiano', 'volume', + + 'Music21Exception', + 'SitesException', + 'Music21ObjectException', + 'ElementException', + + 'Groups', + 'Music21Object', + 'ElementWrapper', + 'VERSION', ] # ------------------------------------------------------------------------------ diff --git a/music21/common/__init__.py b/music21/common/__init__.py index bea3d4a4c7..f3a6b61443 100644 --- a/music21/common/__init__.py +++ b/music21/common/__init__.py @@ -38,18 +38,31 @@ 'weakrefTools', ] +from music21.common import classTools from music21.common.classTools import * # including isNum, isListLike +from music21.common import decorators from music21.common.decorators import * # gives the deprecated decorator +from music21.common import enums from music21.common.enums import * +from music21.common import fileTools from music21.common.fileTools import * # file tools. +from music21.common import formats from music21.common.formats import * # most are deprecated! +from music21.common import misc from music21.common.misc import * # most are deprecated! +from music21.common import numberTools from music21.common.numberTools import * # including opFrac +from music21.common import objects from music21.common.objects import * +from music21.common import pathTools from music21.common.pathTools import * +from music21.common import parallel from music21.common.parallel import * +from music21.common import stringTools from music21.common.stringTools import * +from music21.common import types from music21.common.types import * +from music21.common import weakrefTools from music21.common.weakrefTools import * # including wrapWeakref DEBUG_OFF = 0 diff --git a/music21/corpus/__init__.py b/music21/corpus/__init__.py index 500a62ab8e..12704fb6ac 100644 --- a/music21/corpus/__init__.py +++ b/music21/corpus/__init__.py @@ -47,7 +47,7 @@ from music21.corpus import chorales from music21.corpus import corpora from music21.corpus import manager -from music21.corpus import virtual +# from music21.corpus import virtual from music21.corpus import work from music21.corpus.manager import search from music21 import environment diff --git a/music21/figuredBass/realizer.py b/music21/figuredBass/realizer.py index 853767ca16..bbfd3b0358 100644 --- a/music21/figuredBass/realizer.py +++ b/music21/figuredBass/realizer.py @@ -61,9 +61,6 @@ from music21.figuredBass import rules from music21.figuredBass import segment -if t.TYPE_CHECKING: - from music21.stream.iterator import StreamIterator - def figuredBassFromStream(streamPart: stream.Stream) -> FiguredBassLine: # noinspection PyShadowingNames diff --git a/music21/metadata/__init__.py b/music21/metadata/__init__.py index 46deee8000..49469f9431 100755 --- a/music21/metadata/__init__.py +++ b/music21/metadata/__init__.py @@ -161,14 +161,9 @@ from music21.metadata.primitives import ( Contributor, Copyright, - Creator, Date, - DateBetween, DatePrimitive, - DateRelative, - DateSelection, DateSingle, - Imprint, Text, ValueType, ) diff --git a/music21/test/__init__.py b/music21/test/__init__.py index 9c680046df..10866d50b2 100644 --- a/music21/test/__init__.py +++ b/music21/test/__init__.py @@ -1,5 +1,17 @@ from __future__ import annotations +__all__ = [ + 'base', + 'chord', + 'clef', + 'expressions', + 'interval', + 'metadata', + 'note', + 'pitch', + 'repeat', +] + from music21.test import test_base as base from music21.test import test_chord as chord from music21.test import test_clef as clef diff --git a/music21/test/commonTest.py b/music21/test/commonTest.py index b1922bd159..c8fa97f706 100644 --- a/music21/test/commonTest.py +++ b/music21/test/commonTest.py @@ -21,7 +21,6 @@ import sys import typing import types -import unittest import unittest.runner from unittest.signals import registerResult import warnings @@ -91,12 +90,12 @@ def testImports(): ''' # pylint: disable=unused-import try: - import scipy # type: ignore + import scipy # type: ignore # noqa: F401 except ImportError as e: raise ImportError('pip install scipy : needed for running test suites') from e try: - from Levenshtein import StringMatcher # type: ignore + from Levenshtein import StringMatcher # type: ignore # noqa: F401 except ImportError as e: raise ImportError('pip install python-Levenshtein : needed for running test suites') from e diff --git a/music21/test/coverageM21.py b/music21/test/coverageM21.py index 1fbe89f3a0..2ea878894e 100644 --- a/music21/test/coverageM21.py +++ b/music21/test/coverageM21.py @@ -52,7 +52,7 @@ def getCoverage(overrideVersion=False): for e in exclude_lines: cov.exclude(e, which='exclude') cov.start() - import music21 # pylint: disable=unused-import + import music21 # pylint: disable=unused-import # noqa: F401 except ImportError: cov = None else: diff --git a/music21/tree/trees.py b/music21/tree/trees.py index 07a8f04f89..47ae1321ef 100644 --- a/music21/tree/trees.py +++ b/music21/tree/trees.py @@ -16,7 +16,6 @@ from __future__ import annotations from math import inf -import typing as t import unittest import weakref @@ -439,7 +438,6 @@ def _updateParents(self, oldPosition, visitedParents=None): if parent is None or parent in visitedParents: continue visitedParents.add(parent) - parentPosition = parent.offset parent._removeElementAtPosition(self, oldPosition) # Trees don't have offsets currently raise NotImplementedError diff --git a/pyproject.toml b/pyproject.toml index 46e692cf6c..0ca8f78845 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -76,7 +76,9 @@ line-length = 100 [tool.ruff.lint] # Flake8 core (pycodestyle + pyflakes) + flake8-quotes -select = ['E', 'Q'] +select = ['E', 'Q', 'F'] + +dummy-variable-rgx = "^(_.*|unused.*|i|j|counter|junk|dummy)" # add once allowed: E122 (continuation line missing indentation) and E124 (bracket align) @@ -104,7 +106,7 @@ ignore = [ 'music21/musicxml/testFiles.py' = ['E501'] # line-too-long 'music21/musicxml/testPrimitive.py' = ['E501'] # line-too-long 'music21/romanText/testFiles.py' = ['E501'] # line-too-long -'music21/search/__init__.py' = ['F403'] +'music21/search/__init__.py' = ['F403', 'F405'] # 405--star exports fine 'music21/variant.py' = ['E501'] # line-too-long [tool.ruff.lint.flake8-quotes] From 738a2c20337e6cf0a560635913e5c1af7036516e Mon Sep 17 00:00:00 2001 From: Michael Scott Asato Cuthbert Date: Fri, 2 Jan 2026 16:56:08 -1000 Subject: [PATCH 04/13] Remove % interpolation --- music21/analysis/pitchAnalysis.py | 6 +- music21/analysis/reduceChords.py | 8 +-- music21/analysis/reduceChordsOld.py | 8 +-- music21/analysis/windowed.py | 3 +- music21/audioSearch/__init__.py | 2 +- music21/audioSearch/recording.py | 1 - music21/audioSearch/scoreFollower.py | 4 +- music21/base.py | 2 +- music21/braille/segment.py | 13 +++-- music21/chord/tables.py | 4 +- music21/common/parallel.py | 4 +- music21/configure.py | 6 +- music21/converter/__init__.py | 5 +- music21/corpus/chorales.py | 2 +- music21/dynamics.py | 6 +- music21/features/base.py | 26 +++++---- music21/freezeThaw.py | 6 +- music21/graph/axis.py | 2 +- music21/graph/primitives.py | 2 +- music21/harmony.py | 5 +- music21/humdrum/spineParser.py | 6 +- music21/interval.py | 2 +- music21/key.py | 2 +- music21/lily/translate.py | 11 ++-- music21/meter/base.py | 7 ++- music21/meter/core.py | 27 +++++---- music21/meter/tests.py | 5 +- music21/midi/translate.py | 16 ++++-- music21/musedata/__init__.py | 6 +- music21/musicxml/m21ToXml.py | 18 +++--- music21/musicxml/partStaffExporter.py | 6 +- music21/musicxml/xmlSoundParser.py | 2 +- music21/musicxml/xmlToM21.py | 32 +++++++---- music21/noteworthy/translate.py | 4 +- music21/omr/correctors.py | 9 ++- music21/pitch.py | 2 +- music21/repeat.py | 18 +++--- music21/romanText/rtObjects.py | 14 +++-- music21/romanText/translate.py | 46 ++++++++-------- music21/romanText/tsvConverter.py | 3 +- music21/scale/__init__.py | 7 --- music21/scale/intervalNetwork.py | 2 +- music21/search/base.py | 24 +++++--- music21/sieve.py | 6 +- music21/sites.py | 13 +++-- music21/spanner.py | 10 ++-- music21/stream/base.py | 79 +++++++++++++-------------- music21/stream/core.py | 4 +- music21/stream/filters.py | 4 +- music21/stream/iterator.py | 10 ++-- music21/stream/makeNotation.py | 13 +++-- music21/style.py | 9 +-- music21/tempo.py | 3 +- music21/test/memoryUsage.py | 4 +- music21/test/multiprocessTest.py | 42 +++++++------- music21/test/test_base.py | 2 +- music21/test/treeYield.py | 6 +- music21/tree/timespanTree.py | 11 ++-- music21/tree/trees.py | 6 +- music21/voiceLeading.py | 8 +-- pyproject.toml | 6 +- 61 files changed, 339 insertions(+), 281 deletions(-) diff --git a/music21/analysis/pitchAnalysis.py b/music21/analysis/pitchAnalysis.py index 4adc9d4518..bcbda27e05 100644 --- a/music21/analysis/pitchAnalysis.py +++ b/music21/analysis/pitchAnalysis.py @@ -21,7 +21,7 @@ def pitchAttributeCount(s, pitchAttr='name'): >>> bach = corpus.parse('bach/bwv324.xml') >>> pcCount = analysis.pitchAnalysis.pitchAttributeCount(bach, 'pitchClass') >>> for n in sorted(pcCount): - ... print("%2d: %2d" % (n, pcCount[n])) + ... print(f'{n:2d}: {pcCount[n]:2d}') 0: 3 2: 26 3: 3 @@ -36,7 +36,7 @@ def pitchAttributeCount(s, pitchAttr='name'): >>> nameCount = analysis.pitchAnalysis.pitchAttributeCount(bach, 'name') >>> for n, count in nameCount.most_common(3): - ... print("%2s: %2d" % (n, nameCount[n])) + ... print(f'{n:2s}: {nameCount[n]:2d}') D: 26 A: 17 F#: 15 @@ -44,7 +44,7 @@ def pitchAttributeCount(s, pitchAttr='name'): >>> nameOctaveCount = analysis.pitchAnalysis.pitchAttributeCount(bach, 'nameWithOctave') >>> for n in sorted(nameOctaveCount): - ... print("%3s: %2d" % (n, nameOctaveCount[n])) + ... print(f'{n:3s}: {nameOctaveCount[n]:2d}') A2: 2 A3: 5 A4: 10 diff --git a/music21/analysis/reduceChords.py b/music21/analysis/reduceChords.py index ec0d477949..6913bfc8f7 100644 --- a/music21/analysis/reduceChords.py +++ b/music21/analysis/reduceChords.py @@ -320,7 +320,7 @@ def computeMeasureChordWeights( >>> cr = analysis.reduceChords.ChordReducer() >>> cws = cr.computeMeasureChordWeights(s) >>> for pcs in sorted(cws): - ... print("%18r %2.1f" % (pcs, cws[pcs])) + ... print(f'{pcs!r:18} {cws[pcs]:2.1f}') (0, 4, 7) 3.0 (0, 11, 4, 5) 1.0 @@ -329,7 +329,7 @@ def computeMeasureChordWeights( >>> cws = cr.computeMeasureChordWeights(s, ... weightAlgorithm=cr.quarterLengthBeatStrength) >>> for pcs in sorted(cws): - ... print("%18r %2.1f" % (pcs, cws[pcs])) + ... print(f'{pcs!r:18} {cws[pcs]:2.1f}') (0, 4, 7) 2.2 (0, 11, 4, 5) 0.5 @@ -338,7 +338,7 @@ def computeMeasureChordWeights( >>> cws = cr.computeMeasureChordWeights(s, ... weightAlgorithm=cr.quarterLengthBeatStrengthMeasurePosition) >>> for pcs in sorted(cws): - ... print("%18r %2.1f" % (pcs, cws[pcs])) + ... print(f'{pcs!r:18} {cws[pcs]:2.1f}') (0, 4, 7) 3.0 (0, 11, 4, 5) 0.5 @@ -347,7 +347,7 @@ def computeMeasureChordWeights( >>> cws = cr.computeMeasureChordWeights(s, ... weightAlgorithm=cr.qlbsmpConsonance) >>> for pcs in sorted(cws): - ... print("%18r %2.1f" % (pcs, cws[pcs])) + ... print(f'{pcs!r:18} {cws[pcs]:2.1f}') (0, 4, 7) 3.0 (0, 11, 4, 5) 0.1 ''' diff --git a/music21/analysis/reduceChordsOld.py b/music21/analysis/reduceChordsOld.py index 16e1d7e9e8..2281f8c329 100644 --- a/music21/analysis/reduceChordsOld.py +++ b/music21/analysis/reduceChordsOld.py @@ -159,7 +159,7 @@ def computeMeasureChordWeights(self, measureObj, weightAlgorithm=None): >>> cr = analysis.reduceChordsOld.ChordReducer() >>> cws = cr.computeMeasureChordWeights(s) >>> for pcs in sorted(cws): - ... print("%18r %2.1f" % (pcs, cws[pcs])) + ... print(f'{pcs!r:18} {cws[pcs]:2.1f}') (0, 4, 7) 3.0 (0, 11, 4, 5) 1.0 @@ -167,7 +167,7 @@ def computeMeasureChordWeights(self, measureObj, weightAlgorithm=None): >>> cws = cr.computeMeasureChordWeights(s, weightAlgorithm=cr.quarterLengthBeatStrength) >>> for pcs in sorted(cws): - ... print("%18r %2.1f" % (pcs, cws[pcs])) + ... print(f'{pcs!r:18} {cws[pcs]:2.1f}') (0, 4, 7) 2.2 (0, 11, 4, 5) 0.5 @@ -176,7 +176,7 @@ def computeMeasureChordWeights(self, measureObj, weightAlgorithm=None): >>> cws = cr.computeMeasureChordWeights(s, ... weightAlgorithm=cr.quarterLengthBeatStrengthMeasurePosition) >>> for pcs in sorted(cws): - ... print("%18r %2.1f" % (pcs, cws[pcs])) + ... print(f'{pcs!r:18} {cws[pcs]:2.1f}') (0, 4, 7) 3.0 (0, 11, 4, 5) 0.5 @@ -184,7 +184,7 @@ def computeMeasureChordWeights(self, measureObj, weightAlgorithm=None): >>> cws = cr.computeMeasureChordWeights(s, weightAlgorithm=cr.qlbsmpConsonance) >>> for pcs in sorted(cws): - ... print("%18r %2.1f" % (pcs, cws[pcs])) + ... print(f'{pcs!r:18} {cws[pcs]:2.1f}') (0, 4, 7) 3.0 (0, 11, 4, 5) 0.5 ''' diff --git a/music21/analysis/windowed.py b/music21/analysis/windowed.py index a0c200ddb0..370912c94a 100644 --- a/music21/analysis/windowed.py +++ b/music21/analysis/windowed.py @@ -164,7 +164,8 @@ def analyze(self, windowSize, windowType='overlap'): windowCount = int(windowCountFloat) if windowCountFloat != windowCount: warnings.warn( - 'maxWindowCount is not divisible by windowSize, possibly undefined behavior' + 'maxWindowCount is not divisible by windowSize, possibly undefined behavior', + stacklevel=2 ) elif windowType == 'adjacentAverage': windowCount = maxWindowCount diff --git a/music21/audioSearch/__init__.py b/music21/audioSearch/__init__.py index 6732e89321..9fb7347c43 100644 --- a/music21/audioSearch/__init__.py +++ b/music21/audioSearch/__init__.py @@ -151,7 +151,7 @@ def autocorrelationFunction(recordedSignal, recordSampleRateIn): # noinspection PyPackageRequirements from scipy.signal import fftconvolve as convolve # type: ignore except ImportError: # pragma: no cover - warnings.warn('Running convolve without scipy -- will be slower') + warnings.warn('Running convolve without scipy -- will be slower', stacklevel=2) convolve = numpy.convolve recordedSignal = numpy.array(recordedSignal) diff --git a/music21/audioSearch/recording.py b/music21/audioSearch/recording.py index 64802018b2..0c18b47401 100644 --- a/music21/audioSearch/recording.py +++ b/music21/audioSearch/recording.py @@ -74,7 +74,6 @@ def samplesFromRecording(seconds=10.0, storeFile=True, for i in range(recordingLength): data = st.read(recordChunkLength) storedWaveSampleList.append(data) - # print('Time elapsed: %.3f s\n' % (time.time() - time_start)) st.close() p_audio.terminate() diff --git a/music21/audioSearch/scoreFollower.py b/music21/audioSearch/scoreFollower.py index e705c35f91..fd5c63222d 100644 --- a/music21/audioSearch/scoreFollower.py +++ b/music21/audioSearch/scoreFollower.py @@ -126,9 +126,9 @@ def repeatTranscription(self): # print('WE STAY AT:',) # print(self.lastNotePosition, len(self.scoreNotesOnly),) - # print('en percent %s %%' % (self.lastNotePosition * 100 / len(self.scoreNotesOnly)),) + # print(f'en percent {self.lastNotePosition * 100 / len(self.scoreNotesOnly}%') # print(' this search begins at: ', self.startSearchAtSlot,) - # print('countdown %s' % self.countdown) + # print(f'countdown {self.countdown}') # print('Measure last note', self.scoreStream[self.lastNotePosition].measureNumber) environLocal.printDebug('repeat transcription starting') diff --git a/music21/base.py b/music21/base.py index 8f6b3599ba..b6969d46b6 100644 --- a/music21/base.py +++ b/music21/base.py @@ -588,7 +588,7 @@ def id(self, new_id: int|str): if isinstance(new_id, int) and new_id > defaults.minIdNumberToConsiderMemoryLocation: msg = 'Setting an ID that could be mistaken for a memory location ' msg += f'is discouraged: got {new_id}' - warnings.warn(msg) + warnings.warn(msg, stacklevel=2) self._id = new_id def mergeAttributes(self, other: Music21Object) -> None: diff --git a/music21/braille/segment.py b/music21/braille/segment.py index f934f3d7c9..adf7f0e056 100644 --- a/music21/braille/segment.py +++ b/music21/braille/segment.py @@ -1240,13 +1240,14 @@ def matchOther(thisKey_inner, otherKey): # gkLeft = gkRight._replace(affinity=gkRight.affinity - 1) # try: # groupingKeysLeft.remove(gkLeft) - # except ValueError: + # except ValueError as ve: # raise BrailleSegmentException( - # 'Misaligned braille groupings: ' + - # 'groupingKeyLeft was %s' % gkLeft + - # 'groupingKeyRight was %s' % gkRight + - # 'rightSegment was %s, leftSegment was %s' % - # (rightSegment, leftSegment)) + # 'Misaligned braille groupings: ' + # + f'groupingKeyLeft was {gkLeft} ' + # + f'groupingKeyRight was {gkRight} ' + # + f'rightSegment was {rightSegment}, ' + # + f'leftSegment was {leftSegment}' + # ) from ve # # try: # combinedGroupingTuple = (gkRight, gkLeft) diff --git a/music21/chord/tables.py b/music21/chord/tables.py index 0dfcee549d..0cc4e84031 100644 --- a/music21/chord/tables.py +++ b/music21/chord/tables.py @@ -1561,8 +1561,8 @@ def _validateAddress(address): # ultimately this can be removed # try: # nfSet = cardinalityToChordMembers[card][(index, inversion)][0] - # except KeyError: - # raise ChordTablesException('cannot validate address: %s' % address) + # except KeyError as ke: + # raise ChordTablesException(f'cannot validate address: {address}') from ke return (card, index, inversion) diff --git a/music21/common/parallel.py b/music21/common/parallel.py index f6942a2471..6703db6a10 100644 --- a/music21/common/parallel.py +++ b/music21/common/parallel.py @@ -70,7 +70,7 @@ def runParallel(iterable, parallelFunction, *, With a custom updateFunction that gets each output: >>> def yak(position, length, output): - ... print("%s:%s %s is a lot of notes!" % (position, length, output)) + ... print(f'{position}:{length} {output} is a lot of notes!') >>> #_DOCS_SHOW outputs = common.runParallel(files, countNotes, updateFunction=yak) >>> outputs = common.runNonParallel(files, countNotes, updateFunction=yak) #_DOCS_HIDE 0:3 165 is a lot of notes! @@ -80,7 +80,7 @@ def runParallel(iterable, parallelFunction, *, Or with updateSendsIterable, we can get the original files data as well: >>> def yik(position, length, output, fn): - ... print("%s:%s (%s) %s is a lot of notes!" % (position, length, fn, output)) + ... print(f'{position}:{length} ({fn}) {output} is a lot of notes!') >>> #_DOCS_SHOW outputs = common.runParallel(files, countNotes, updateFunction=yik, >>> outputs = common.runNonParallel(files, countNotes, updateFunction=yik, #_DOCS_HIDE ... updateSendsIterable=True) diff --git a/music21/configure.py b/music21/configure.py index 8045d81505..3759fe93cf 100644 --- a/music21/configure.py +++ b/music21/configure.py @@ -1419,7 +1419,7 @@ def run(self, forceList=None): # self.timeLeft -= value # # def printPrompt(self): -# sys.stdout.write('%s: ' % self.prompt) +# sys.stdout.write(f'{self.prompt}: ') # # def run(self): # self.printPrompt() # print on first call @@ -1445,7 +1445,7 @@ def run(self, forceList=None): # current.removeTime(updateInterval) # # if intervalCount % reportInterval == reportInterval - 1: -# sys.stdout.write('\n time out in %s seconds\n' % current.timeLeft) +# sys.stdout.write(f'\n time out in {current.timeLeft} seconds\n') # current.printPrompt() # # intervalCount += 1 @@ -1459,7 +1459,7 @@ def run(self, forceList=None): # if post == None: # print('got no value') # else: -# print('got: %s' % post) +# print(f'got: {post}') # ------------------------------------------------------------------------------ # define presented order in documentation _DOC_ORDER: list[type] = [] diff --git a/music21/converter/__init__.py b/music21/converter/__init__.py index 2ba1837c26..71e4b9108d 100644 --- a/music21/converter/__init__.py +++ b/music21/converter/__init__.py @@ -706,8 +706,9 @@ def parseData( elif 'Time Signature:' in dataStrMakeStr and 'm1' in dataStrMakeStr: useFormat = 'romanText' else: - raise ConverterException('File not found or no such format found for: %s' % - dataStrMakeStr) + raise ConverterException( + f'File not found or no such format found for: {dataStrMakeStr}' + ) self.setSubConverterFromFormat(useFormat) if t.TYPE_CHECKING: diff --git a/music21/corpus/chorales.py b/music21/corpus/chorales.py index 09b636e610..e6a2386813 100644 --- a/music21/corpus/chorales.py +++ b/music21/corpus/chorales.py @@ -1168,7 +1168,7 @@ def __next__(self): _currentIndex becomes higher than the _highestIndex, the iteration stops. ''' if self._currentIndex > self._highestIndex: - raise StopIteration + raise StopIteration() nextChorale = self._returnChorale() self._currentIndex += 1 return nextChorale diff --git a/music21/dynamics.py b/music21/dynamics.py index 764667f407..112154f67c 100644 --- a/music21/dynamics.py +++ b/music21/dynamics.py @@ -127,7 +127,7 @@ class Dynamic(base.Music21Object): >>> ppp = dynamics.Dynamic(0.15) # on 0 to 1 scale >>> ppp.value 'ppp' - >>> print('%.2f' % ppp.volumeScalar) + >>> print(f'{ppp.volumeScalar:.2f}') 0.15 Note that we got lucky last time because the dynamic 0.15 exactly corresponds @@ -138,7 +138,7 @@ class Dynamic(base.Music21Object): >>> loud = dynamics.Dynamic(0.98) # on 0 to 1 scale >>> loud.value 'fff' - >>> print('%.2f' % loud.volumeScalar) + >>> print(f'{loud.volumeScalar:.2f}') 0.98 Transferring the .value ('fff') to a new Dynamic object will set the volumeScalar @@ -147,7 +147,7 @@ class Dynamic(base.Music21Object): >>> loud2 = dynamics.Dynamic(loud.value) >>> loud2.value 'fff' - >>> print('%.2f' % loud2.volumeScalar) + >>> print(f'{loud2.volumeScalar:.2f}') 0.90 Custom dynamics are possible: diff --git a/music21/features/base.py b/music21/features/base.py index 61183da4dc..2cbc216a73 100644 --- a/music21/features/base.py +++ b/music21/features/base.py @@ -1692,8 +1692,11 @@ def x_testRegionClassificationJSymbolicB(self): # pragma: no cover # if c != matchData[i].getclass(): # mismatch += 1 # - # print('%s %s: misclassified %s/%s of %s' % ( - # classifierStr, classifierType, mismatch, len(matchData), matchStr)) + # print( + # f'{classifierStr} {classifierType}: misclassified ' + # + f'{mismatch}/{len(matchData)} of ' + # + f'{matchStr}' + # ) # # # if classifierType == orngTree.TreeLearner: # # orngTree.printTxt(classifier) @@ -1741,9 +1744,11 @@ def x_testRegionClassificationJSymbolicB(self): # pragma: no cover # if c != matchData[i].getclass(): # mismatch += 1 # - # print('%s %s: misclassified %s/%s of %s' % ( - # classifierStr, classifierType, mismatch, len(matchData), matchStr)) - + # print( + # f'{classifierStr} {classifierType}: misclassified ' + # + f'{mismatch}/{len(matchData)} of ' + # + f'{matchStr}' + # ) # def xtestOrangeClassifiers(self): # pragma: no cover # ''' @@ -1770,17 +1775,16 @@ def x_testRegionClassificationJSymbolicB(self): # pragma: no cover # print('Possible classes:', data.domain.classVar.values) # print('Original Class', end=' ') # for l in classifiers: - # print('%-13s' % (l.name), end=' ') + # print(f'{l.name:<13}', end=' ') # print() # # for example in data: - # print('(%-10s) ' % (example.getclass()), end=' ') + # print(f'({example.getclass():<10}) ', end=' ') # for c in classifiers: # p = c([example, orange.GetProbabilities]) - # print('%5.3f ' % (p[0]), end=' ') + # print(f'{p[0]:5.3f} ', end=' ') # print('') - # def xtestOrangeClassifierTreeLearner(self): # pragma: no cover # import orange, orngTree # pylint: disable=import-error # data = orange.ExampleTable( @@ -1790,7 +1794,9 @@ def x_testRegionClassificationJSymbolicB(self): # pragma: no cover # # tree = orngTree.TreeLearner(data) # for i in range(len(data)): # p = tree(data[i], orange.GetProbabilities) - # print('%s: %5.3f (originally %s)' % (i + 1, p[1], data[i].getclass())) + # print( + # f'{i + 1}: {p[1]:5.3f} (originally {data[i].getclass()})' + # ) # # orngTree.printTxt(tree) diff --git a/music21/freezeThaw.py b/music21/freezeThaw.py index 2726884b5c..6f5217e2d3 100644 --- a/music21/freezeThaw.py +++ b/music21/freezeThaw.py @@ -1083,9 +1083,11 @@ def x_testSimplePickle(self): # for el in s._elements: # idEl = el.id # if idEl not in storedIds: - # print('Could not find ID %s for element %r at offset %f' % - # (idEl, el, el.offset)) + # print( + # f'Could not find ID {idEl} for element {el!r} at offset {el.offset:f}' + # ) # print(storedIds) + # s.show('t') def x_testFreezeThawPickle(self): diff --git a/music21/graph/axis.py b/music21/graph/axis.py index 329c16b269..969b28c91e 100644 --- a/music21/graph/axis.py +++ b/music21/graph/axis.py @@ -1334,7 +1334,7 @@ def ticks(self): self.setBoundariesFromData() for i in range(self.minValue, self.maxValue + 1): # place string in tex format for italic display - ticks.append((i, r'$%s$' % dynamics.shortNames[i])) + ticks.append((i, f'${dynamics.shortNames[i]}$')) return ticks # ----------------------------------------------------------------------------- diff --git a/music21/graph/primitives.py b/music21/graph/primitives.py index 8fec85c3f5..c69d2c87ec 100644 --- a/music21/graph/primitives.py +++ b/music21/graph/primitives.py @@ -1104,7 +1104,7 @@ def renderSubplot(self, subplot): # for x in range(int(math.floor(xMin)), # round(math.ceil(xMax)), # rangeStep): - # xTicks.append([x, '%s' % x]) + # xTicks.append([x, f'{x}']) # self.setTicks('x', xTicks) # environLocal.printDebug(['xTicks', xTicks]) diff --git a/music21/harmony.py b/music21/harmony.py index 840c6293e9..ac6cafdbbb 100644 --- a/music21/harmony.py +++ b/music21/harmony.py @@ -1429,7 +1429,7 @@ def removeChordSymbols(chordType): class ChordSymbol(Harmony): # noinspection SpellCheckingInspection - ''' + r''' Class representing the Chord Symbols commonly found on lead sheets. Chord Symbol objects can be instantiated one of two main ways: @@ -1485,7 +1485,8 @@ class ChordSymbol(Harmony): ... chordSymbolName = 'C' + s ... h = harmony.ChordSymbol(chordSymbolName) ... pitchNames = [str(p) for p in h.pitches] - ... print('%-10s%s' % (chordSymbolName, '[' + (', '.join(pitchNames)) + ']')) + ... print(f'{chordSymbolName:<10}', end='[') + ... print(*pitchNames, sep=', ', end=']\n') C [C3, E3, G3] Cm [C3, E-3, G3] C+ [C3, E3, G#3] diff --git a/music21/humdrum/spineParser.py b/music21/humdrum/spineParser.py index 3aeef67906..a8beac4e13 100644 --- a/music21/humdrum/spineParser.py +++ b/music21/humdrum/spineParser.py @@ -1096,7 +1096,7 @@ def __next__(self): Returns the current event and increments the iteration index. ''' if self.iterIndex == len(self.eventList): - raise StopIteration + raise StopIteration() thisEvent = self.eventList[self.iterIndex] self.iterIndex += 1 return thisEvent @@ -1627,7 +1627,7 @@ def __next__(self): Returns the current spine and decrements the iteration index. ''' if self.iterIndex < 0: - raise StopIteration + raise StopIteration() thisSpine = self.spines[self.iterIndex] self.iterIndex -= 1 return thisSpine @@ -2937,7 +2937,7 @@ def testSpineMazurka(self): hf1.parse() masterStream = hf1.stream # for spineX in hf1.spineCollection: - # spineX.stream.id = 'spine %s' % str(spineX.id) + # spineX.stream.id = f'spine {spineX.id}' # masterStream.append(spineX.stream) # self.assertTrue(common.whitespaceEqual # (common.stripAddresses(expectedOutput), diff --git a/music21/interval.py b/music21/interval.py index c5ab5a293c..5951a3389b 100644 --- a/music21/interval.py +++ b/music21/interval.py @@ -3500,7 +3500,7 @@ def _diatonicTransposePitch(self, # pitchAlt.ps = pitch2.ps + halfStepsToFix # environLocal.printDebug( # 'coercing pitch due to a transposition that requires an extreme ' + - # 'accidental: %s -> %s' % (pitch2, pitchAlt) ) + # f'accidental: {pitch2} -> {pitchAlt}') # pitch2 = pitchAlt pitch2.ps = pitch2.ps + halfStepsToFix else: diff --git a/music21/key.py b/music21/key.py index 3fdbf229ee..895eb8b892 100644 --- a/music21/key.py +++ b/music21/key.py @@ -431,7 +431,7 @@ def asKey(self, mode: str|None = None, tonic: str|None = None): ''' our_sharps = self.sharps or 0 # || 0 in case of None -- non-standard key-signature if mode is not None and tonic is not None: - warnings.warn(f'ignoring provided tonic: {tonic}', KeyWarning) + warnings.warn(f'ignoring provided tonic: {tonic}', KeyWarning, stacklevel=2) if mode is None and tonic is None: mode = 'major' if mode is None and tonic is not None: diff --git a/music21/lily/translate.py b/music21/lily/translate.py index 095ea7bc4b..ce89f22a5e 100644 --- a/music21/lily/translate.py +++ b/music21/lily/translate.py @@ -313,7 +313,7 @@ def loadFromMusic21Object(self, m21ObjectIn): scoreObj = stream.Score() scoreObj.insert(0, m21ObjectIn) self.loadObjectFromScore(scoreObj, makeNotation=False) - # raise LilyTranslateException('Unknown stream type %s.' % (m21ObjectIn.__class__)) + # raise LilyTranslateException(f'Unknown stream type {m21ObjectIn.__class__}') def loadObjectFromOpus(self, opusIn=None, makeNotation=True): r''' @@ -1088,8 +1088,6 @@ def appendM21ObjectToContext(self, thisObject): lyObject = self.lyPrefixCompositeMusicFromStream(thisObject) currentMusicList.append(lyObject) lyObject.setParent(contextObject) - # except AttributeError as ae: - # raise ValueError('Cannot parse %s: %s' % (thisObject, str(ae))) elif 'Note' in c or 'Rest' in c: self.appendContextFromNoteOrRest(thisObject) elif 'Chord' in c: @@ -2197,18 +2195,19 @@ def lyPrefixCompositeMusicFromVariant(self, simpleString='Staff', music=lpOssiaMusicVariantWithSpacer) - # optionalContextMod = r''' + # optionalContextMod = rf''' # \with { # \remove "Time_signature_engraver" - # alignAboveContext = #"%s" + # alignAboveContext = #"{containerId}" # fontSize = #-3 # \override StaffSymbol.staff-space = #(magstep -3) # \override StaffSymbol.thickness = #(magstep -3) # \override TupletBracket.bracket-visibility = ##f # \override TupletNumber.stencil = ##f # \override Clef.transparent = ##t + # \override BarLine.transparent = ##t # } - # ''' % containerId #\override BarLine.transparent = ##t + # ''' # # is the best way of fixing the #barlines that I have come up with. # lpPrefixCompositeMusicVariant.optionalContextMod = optionalContextMod diff --git a/music21/meter/base.py b/music21/meter/base.py index 848a9f9448..9fa35534ac 100644 --- a/music21/meter/base.py +++ b/music21/meter/base.py @@ -1242,7 +1242,7 @@ def _setDefaultBeamPartitions(self) -> None: self.beamSequence.partition([3] * int(self.numerator / 3)) else: pass # doing nothing will beam all together - # environLocal.printDebug('default beam partitions set to: %s' % self.beamSequence) + # environLocal.printDebug(f'default beam partitions set to: {self.beamSequence}') def _setDefaultAccentWeights(self, depth: int = 3) -> None: ''' @@ -1999,8 +1999,9 @@ def getOffsetFromBeat(self, beat): if beatInt - 1 > len(self.beatSequence) - 1: raise TimeSignatureException( - 'requested beat value (%s) not found in beat partitions (%s) of ts %s' % ( - beatInt, self.beatSequence, self)) + f'requested beat value ({beatInt}) not found in beat partitions ' + + f'({self.beatSequence}) of ts {self}' + ) # get a duration object for the beat; will translate into quarterLength # beat int counts from 1; subtract 1 to get index beatDur = self.beatSequence[beatInt - 1].duration diff --git a/music21/meter/core.py b/music21/meter/core.py index 49e8522a37..1541e2817a 100644 --- a/music21/meter/core.py +++ b/music21/meter/core.py @@ -588,7 +588,7 @@ def _addTerminal(self, value: MeterTerminal|str) -> None: # elif isinstance(value, MeterTerminal): # may be a MeterSequence # mt = value # else: - # raise MeterException('cannot add %s to this sequence' % value) + # raise MeterException(f'cannot add {value} to this sequence') self._partition.append(mt) # clear cache self._levelListCache = {} @@ -1271,7 +1271,7 @@ def load(self, elif common.isIterable(value): # a list of Terminals or Sequence es for obj in value: - # environLocal.printDebug('creating MeterSequence with %s' % obj) + # environLocal.printDebug(f'creating MeterSequence with {obj}') self._addTerminal(obj) self._updateRatio() if targetWeight is not None: @@ -1371,12 +1371,12 @@ def weight(self, value: int | float) -> None: try: totalRatio = self._numerator / self._denominator - except TypeError: + except TypeError as te: raise MeterException( 'Something wrong with the type of ' - + 'this numerator %s %s or this denominator %s %s' % - (self._numerator, type(self._numerator), - self._denominator, type(self._denominator))) + + f'this numerator {self._numerator} {type(self._numerator)} ' + + f'or this denominator {self._denominator} {type(self._denominator)}' + ) from te for mt in self._partition: # for mt in self: @@ -1683,8 +1683,9 @@ def getLevelList(self, levelCount: int, flat: bool = True) -> list[MeterTerminal levelCount - 1, flat) else: # level count is at zero if flat: # make sequence into a terminal - mt = MeterTerminal('%s/%s' % ( - partition_i.numerator, partition_i.denominator)) + mt = MeterTerminal( + f'{partition_i.numerator}/{partition_i.denominator}' + ) # set weight to that of the sequence mt.weight = partition_i.weight mtList.append(mt) @@ -1969,8 +1970,9 @@ def offsetToSpan(self, qLenPos, permitMeterModulus=False): # environLocal.printDebug(['exceeding range:', self, # 'self.duration', self.duration]) raise MeterException( - 'cannot access qLenPos %s when total duration is %s and ts is %s' % ( - qLenPos, self.duration.quarterLength, self)) + f'cannot access qLenPos {qLenPos} when total duration is ' + + f'{self.duration.quarterLength} and ts is {self}' + ) # environLocal.printDebug(['offsetToSpan', 'got qLenPos old', qLenPos]) qLenPos = qLenPos % self.duration.quarterLength @@ -2006,8 +2008,9 @@ def offsetToWeight(self, qLenPos): qLenPos = opFrac(qLenPos) if qLenPos >= self.duration.quarterLength or qLenPos < 0: raise MeterException( - 'cannot access qLenPos %s when total duration is %s and ts is %s' % ( - qLenPos, self.duration.quarterLength, self)) + f'cannot access qLenPos {qLenPos} when total duration is ' + + f'{self.duration.quarterLength} and ts is {self}' + ) iMatch = self.offsetToIndex(qLenPos) return opFrac(self[iMatch].weight) diff --git a/music21/meter/tests.py b/music21/meter/tests.py index a3c0b85978..7256b6b7fd 100644 --- a/music21/meter/tests.py +++ b/music21/meter/tests.py @@ -51,8 +51,9 @@ def testCompound(self): for i in range(8): msg = [] for j in range(1, random.choice([2, 4])): - msg.append('%s/%s' % (random.choice(meterStrNumerator), - random.choice(meterStrDenominator))) + numerator = random.choice(meterStrNumerator) + denominator = random.choice(meterStrDenominator) + msg.append(f'{numerator}/{denominator}') ts = TimeSignature('+'.join(msg)) m = stream.Measure() m.timeSignature = ts diff --git a/music21/midi/translate.py b/music21/midi/translate.py index 585a11723a..00545a8bbf 100644 --- a/music21/midi/translate.py +++ b/music21/midi/translate.py @@ -443,7 +443,6 @@ def midiEventsToNote( try: i = PERCUSSION_MAPPER.midiPitchToInstrument(eOn.pitch) except MIDIPercussionException: - # warnings.warn(str(mpe), TranslateWarning) i = instrument.UnpitchedPercussion() nr.storedInstrument = i # TODO: set reasonable displayPitch? @@ -679,7 +678,6 @@ def midiEventsToChord( try: i = PERCUSSION_MAPPER.midiPitchToInstrument(midi_pitch) except MIDIPercussionException: - # warnings.warn(str(mpe), TranslateWarning) i = instrument.UnpitchedPercussion() unp.storedInstrument = i c.add(unp) @@ -938,7 +936,9 @@ def midiEventToInstrument( except UnicodeDecodeError: warnings.warn( f'Unable to determine instrument from {event}; getting generic Instrument', - TranslateWarning) + TranslateWarning, + stacklevel=2, + ) i = instrument.Instrument() except instrument.InstrumentException: # Debug logging would be better than warning here @@ -1059,7 +1059,8 @@ def timeSignatureToMidiEvents(ts, includeDeltaTime=True) -> list[DeltaTime|MidiE if n > 255: warnings.warn( f'TimeSignature with numerator > 255 cannot be stored in MIDI. Ignoring {ts}', - TranslateWarning + TranslateWarning, + stacklevel=2 ) return [] @@ -1958,7 +1959,9 @@ def lyricTimingsFromEvents( except UnicodeDecodeError: warnings.warn( f'Unable to decode lyrics from {e} as {encoding}', - TranslateWarning) + TranslateWarning, + stacklevel=2, + ) return lyrics @@ -2460,7 +2463,8 @@ def channelInstrumentData( f'{inst} specified 1-indexed MIDI channel {thisChannel} ' f'but acceptable channels were {acceptableChannels}. ' 'Defaulting to channel 1.', - TranslateWarning) + TranslateWarning, + stacklevel=2) thisChannel = 1 channelsAssigned.add(thisChannel) channelByInstrument[inst.midiProgram] = thisChannel diff --git a/music21/musedata/__init__.py b/music21/musedata/__init__.py index d2226e4156..0211863ed5 100644 --- a/music21/musedata/__init__.py +++ b/music21/musedata/__init__.py @@ -602,7 +602,7 @@ def __iter__(self): def __next__(self): if self.index >= len(self.src): - raise StopIteration + raise StopIteration() # add one b/c end is inclusive mdr = MuseDataRecord(self.src[self.index], self.parent) self.index += 1 @@ -763,7 +763,7 @@ def __iter__(self): def __next__(self): if self.index >= len(self.boundaries): - raise StopIteration + raise StopIteration() start, end = self.boundaries[self.index] # add one b/c end is inclusive mdm = MuseDataMeasure(self.src[start:end + 1], self.parent) @@ -1584,7 +1584,7 @@ def addFile(self, fp: str | Iterable[str]) -> None: for fpInner in fpList: mdf = MuseDataFile() mdf.encoding = self.encoding - # environLocal.printDebug('processing MuseData file: %s' % fp) + # environLocal.printDebug(f'processing MuseData file: {fp}') mdf.open(fpInner) mdf.read() # process string and break into parts mdf.close() diff --git a/music21/musicxml/m21ToXml.py b/music21/musicxml/m21ToXml.py index 96d0caa972..e9ccfc53f7 100644 --- a/music21/musicxml/m21ToXml.py +++ b/music21/musicxml/m21ToXml.py @@ -424,8 +424,11 @@ def fromScore(self, sc): if self.makeNotation: sc.makeNotation(inPlace=True) if not sc.isWellFormedNotation(): - warnings.warn(f'{sc} is not well-formed; see isWellFormedNotation()', - category=MusicXMLWarning) + warnings.warn( + f'{sc} is not well-formed; see isWellFormedNotation()', + category=MusicXMLWarning, + stacklevel=2, + ) # sc.makeImmutable() return sc @@ -2867,7 +2870,7 @@ def fixupNotationMeasured(self): except exceptions21.StreamException as se: # no measures or no time sig? # incorrectly flagging MusicXMLWarning as not a Warning # noinspection PyTypeChecker - warnings.warn(MusicXMLWarning, str(se)) + warnings.warn(MusicXMLWarning, str(se), stacklevel=2) if not part.streamStatus.tuplets: for m in measures: for m_or_v in [m, *m.voices]: @@ -5400,7 +5403,7 @@ def articulationToXmlArticulation( break if musicXMLArticulationName is None: musicXMLArticulationName = 'other-articulation' - # raise MusicXMLExportException('Cannot translate %s to musicxml' % articulationMark) + # raise MusicXMLExportException(f'Cannot translate {articulationMark} to musicxml') mxArticulationMark = Element(musicXMLArticulationName) if articulationMark.placement is not None: mxArticulationMark.set('placement', articulationMark.placement) @@ -6164,7 +6167,7 @@ def dynamicToXml(self, d: dynamics.Dynamic) -> Element: or whatever: >>> ppp = dynamics.Dynamic('ppp') - >>> print('%.2f' % ppp.volumeScalar) + >>> print(f'{ppp.volumeScalar:.2f}') 0.15 >>> ppp.style.relativeY = -10 @@ -6905,8 +6908,9 @@ def beamToXml(self, beamObject): mxBeam.text = 'forward hook' else: raise MusicXMLExportException( - 'partial beam defined without a proper direction set (set to %s)' % - beamObject.direction) + 'partial beam defined without a proper direction set ' + + f'(set to {beamObject.direction})' + ) else: raise MusicXMLExportException( f'unexpected beam type encountered ({beamObject.type})' diff --git a/music21/musicxml/partStaffExporter.py b/music21/musicxml/partStaffExporter.py index abe52486a4..7f383ec3bb 100644 --- a/music21/musicxml/partStaffExporter.py +++ b/music21/musicxml/partStaffExporter.py @@ -267,7 +267,11 @@ def joinableGroups(self) -> list[StaffGroup]: joinable_components_list = flattenList(deduplicatedGroups) if len(set(joinable_components_list)) != len(joinable_components_list): warnings.warn( - MusicXMLWarning('Got overlapping StaffGroups; will not merge ANY groups.')) + MusicXMLWarning( + 'Got overlapping StaffGroups; will not merge ANY groups.' + ), + stacklevel=2, + ) return [] # Finally, store a reference to earlier siblings (if any) on PartExporters diff --git a/music21/musicxml/xmlSoundParser.py b/music21/musicxml/xmlSoundParser.py index df9f47b94b..56c0f2d333 100644 --- a/music21/musicxml/xmlSoundParser.py +++ b/music21/musicxml/xmlSoundParser.py @@ -107,7 +107,7 @@ def setSoundTempo( qpm = common.numToIntOrFloat(float(mxSound.get('tempo', 0))) if qpm == 0: - warnings.warn('0 qpm tempo tag found, skipping.') + warnings.warn('0 qpm tempo tag found, skipping.', stacklevel=2) return mm = tempo.MetronomeMark(referent=duration.Duration(type='quarter'), number=None, diff --git a/music21/musicxml/xmlToM21.py b/music21/musicxml/xmlToM21.py index 629faa7b89..10a58b1154 100644 --- a/music21/musicxml/xmlToM21.py +++ b/music21/musicxml/xmlToM21.py @@ -1732,14 +1732,14 @@ def _adjustMidiData(mc): i = pm.midiPitchToInstrument(_adjustMidiData(midiUnpitchedText)) except MIDIPercussionException as mpe: # objects not yet existing in m21 such as Cabasa - warnings.warn(MusicXMLWarning(mpe)) + warnings.warn(MusicXMLWarning(mpe), stacklevel=2) i = instrument.UnpitchedPercussion() i.percMapPitch = _adjustMidiData(midiUnpitchedText) elif midiProgramText := strippedText(mxMidiProgram): try: i = instrument.instrumentFromMidiProgram(_adjustMidiData(midiProgramText)) except instrument.InstrumentException as ie: - warnings.warn(MusicXMLWarning(ie)) + warnings.warn(MusicXMLWarning(ie), stacklevel=2) # Invalid MIDI program, out of range 0-127 i = instrument.Instrument() seta(i, mxMIDIInstrument, 'midi-channel', transform=_adjustMidiData) @@ -2020,7 +2020,8 @@ def xmlMeasureToMeasure(self, mxMeasure: ET.Element) -> stream.Measure: warnings.warn( f'The following exception took place in m. {measureParser.measureNumber} in ' + f'part {self.stream.partName}.', - MusicXMLWarning + MusicXMLWarning, + stacklevel=2 ) raise e @@ -2105,7 +2106,9 @@ def updateTransposition(self, newTransposition: interval.Interval): # and create a Generic Instrument object rather than dying. warnings.warn( 'Received a transposition tag, but no instrument to put it on!', - MusicXMLWarning) + MusicXMLWarning, + stacklevel=2, + ) fakeInst = instrument.Instrument() self.activeInstrument = fakeInst self.stream.coreInsert(self.lastMeasureOffset, fakeInst) @@ -2266,7 +2269,8 @@ def adjustTimeAttributesFromMeasure(self, m: stream.Measure): f'Warning: measure {m.number} in part {self.stream.partName}' f'is overfull: {mHighestTime} > {lastTimeSignatureQuarterLength},' f'assuming {mOffsetShift} is correct.', - MusicXMLWarning + MusicXMLWarning, + stacklevel=2, ) elif (mHighestTime == 0.0 and not m.recurse().notesAndRests.getElementsNotOfClass('Harmony') @@ -4345,7 +4349,11 @@ def xmlDirectionTypeToSpanners( 'Line', idFound, False)[0] # get first except IndexError: - warnings.warn('Line <' + mxObj.tag + '> stop without start', MusicXMLWarning) + warnings.warn( + 'Line <' + mxObj.tag + '> stop without start', + MusicXMLWarning, + stacklevel=2, + ) return [] sp.completeStatus = True @@ -5045,7 +5053,7 @@ def findM21VoiceFromXmlVoice( if useVoice is None: # pragma: no cover warnings.warn('Cannot put in an element with a missing voice tag when ' + 'no previous voice tag was given. Assuming voice 1... ', - MusicXMLWarning) + MusicXMLWarning, stacklevel=2) useVoice = 1 thisVoice: stream.Voice|None = None @@ -5058,13 +5066,13 @@ def findM21VoiceFromXmlVoice( else: warnings.warn( f'Cannot find voice {useVoice!r}; putting outside of voices.', - MusicXMLWarning) + MusicXMLWarning, stacklevel=2) warnings.warn( f'Current voiceIds: {list(self.voicesById)}', - MusicXMLWarning) + MusicXMLWarning, stacklevel=2) warnings.warn( f'Current voices: {list(m.voices)} in m. {m.number}', - MusicXMLWarning) + MusicXMLWarning, stacklevel=2) return thisVoice @@ -5513,7 +5521,7 @@ def setDirectionInDirectionType( mxDir, staffKey, totalOffset ) except MusicXMLImportException as excep: - warnings.warn(f'Could not import {tag}: {excep}', MusicXMLWarning) + warnings.warn(f'Could not import {tag}: {excep}', MusicXMLWarning, stacklevel=2) spannerList = [] for sp in spannerList: @@ -6353,7 +6361,7 @@ def xmlStaffLayoutFromStaffDetails( stl.staffType = stream.enums.StaffType(xmlText) except ValueError: warnings.warn( - f'Got an incorrect staff-type in details: {mxStaffType}', MusicXMLWarning) + f'Got an incorrect staff-type in details: {mxStaffType}', MusicXMLWarning, stacklevel=2) # TODO: staff-tuning* # TODO: capo seta(stl, mxDetails, 'staff-size', transform=_floatOrIntStr) diff --git a/music21/noteworthy/translate.py b/music21/noteworthy/translate.py index 7666fb8d45..86abeb7f7f 100644 --- a/music21/noteworthy/translate.py +++ b/music21/noteworthy/translate.py @@ -218,7 +218,7 @@ def parseList(self, dataList): elif command == 'TimeSig': self.createTimeSignature(attributes) except Exception as e: - print('Cannot create object from "%s"' % (attributes)) + print(f'Cannot create object from "{attributes}"') raise NoteworthyTranslateException from e # Add the last Stuff @@ -904,7 +904,7 @@ def createDynamicVariance(self, attributes): g = dynamics.Diminuendo() else: pass - # raise NoteworthyTranslateException('Cannot get style from %s' % str(attributes)) + # raise NoteworthyTranslateException(f'Cannot get style from {attributes}') if g is not None: self.currentMeasure.append(g) diff --git a/music21/omr/correctors.py b/music21/omr/correctors.py index c6effb9263..bc7c6fd45b 100644 --- a/music21/omr/correctors.py +++ b/music21/omr/correctors.py @@ -188,7 +188,7 @@ def getVerticalProbabilityDistributionSinglePart(self, pn): >>> omrScore = converter.parse(omrPath) >>> ssOMR = omr.correctors.ScoreCorrector(omrScore) >>> allDists = ssOMR.getVerticalProbabilityDistributionSinglePart(1) - >>> ['%0.3f' % p for p in allDists] + >>> [f'{p:0.3f}' for p in allDists] ['0.571', '1.000', '0.667', '0.714'] ''' i = pn @@ -1005,8 +1005,11 @@ def differenceProbabilityForOneOpCode(self, opCodeTuple, source, destination=Non 'PFFPFF' >>> opCodes = vlnIIMH.getOpCodes(violaMH.hashString) >>> for oc in opCodes: - ... print('%30r : %.3f' % - ... (oc, vlnIIMH.differenceProbabilityForOneOpCode(oc, violaMH.hashString))) + ... prob = vlnIIMH.differenceProbabilityForOneOpCode( + ... oc, + ... violaMH.hashString, + ... ) + ... print(f'{oc!r:>30} : {prob:.3f}') ('equal', 0, 1, 0, 1) : 0.968 ('replace', 1, 2, 1, 2) : 0.009 ('equal', 2, 6, 2, 6) : 0.876 diff --git a/music21/pitch.py b/music21/pitch.py index 5d6231bb3e..c78bc2388c 100644 --- a/music21/pitch.py +++ b/music21/pitch.py @@ -2592,7 +2592,7 @@ def ps(self): >>> p = pitch.Pitch('c4') >>> p.microtone = 20 - >>> print('%.1f' % p.ps) + >>> print(f'{p.ps:.1f}') 60.2 Octaveless pitches use their .implicitOctave attributes: diff --git a/music21/repeat.py b/music21/repeat.py index f0138c627d..424a1dc9f2 100644 --- a/music21/repeat.py +++ b/music21/repeat.py @@ -61,7 +61,7 @@ class RepeatMark(prebase.ProtoM21Object): >>> s.append(PartialRepeat()) >>> repeats = s.getElementsByClass('RepeatMark') # not a Music21Object, so use quotes >>> if repeats: - ... print('Stream has %s repeat(s) in it' % (len(repeats))) + ... print(f'Stream has {len(repeats)} repeat(s) in it') Stream has 1 repeat(s) in it ''' @@ -877,7 +877,7 @@ def _stripRepeatBarlines(self, m, newType='double'): lb = m.leftBarline rb = m.rightBarline if lb is not None and 'music21.bar.Repeat' in lb.classSet: - # environLocal.printDebug(['inserting new barline: %s' % newStyle]) + # environLocal.printDebug([f'inserting new barline: {newStyle}']) m.leftBarline = bar.Barline(newType) if rb is not None and 'music21.bar.Repeat' in rb.classSet: m.rightBarline = bar.Barline(newType) @@ -940,11 +940,15 @@ def repeatBarsAreCoherent(self): environLocal.printDebug([f'Repeats are not balanced: countBalance: {countBalance}']) return False if startCount not in (endCount, endCount - 1): - environLocal.printDebug(['start count not the same as end count: %s / %s' % ( - startCount, endCount)]) + environLocal.printDebug([ + 'start count not the same as end count: ' + + f'{startCount} / {endCount}' + ]) return False - # environLocal.printDebug(['matched start and end repeat barline count of: ', - # '%s/%s' % (startCount, endCount)]) + # environLocal.printDebug([ + # 'matched start and end repeat barline count of: ' + # + f'{startCount}/{endCount}' + # ]) return True def _daCapoOrSegno(self): @@ -1276,7 +1280,7 @@ def findInnermostRepeatIndices(self, streamObj): # an end may be placed on the left barline; of the next measure # meaning that we only want up until the previous elif lb.direction == 'end': - # environLocal.printDebug(['found an end in left barline: %s' % lb]) + # environLocal.printDebug([f'found an end in left barline: {lb}']) if not startIndices: # get from first to this one barRepeatIndices = range(i) diff --git a/music21/romanText/rtObjects.py b/music21/romanText/rtObjects.py index 06a79eac54..0e742ae16b 100644 --- a/music21/romanText/rtObjects.py +++ b/music21/romanText/rtObjects.py @@ -824,8 +824,10 @@ def getOffset(self, timeSignature): try: post = timeSignature.getOffsetFromBeat(beat) except exceptions21.TimeSignatureException: - environLocal.printDebug(['bad beat specification: %s in a meter of %s' % ( - self.src, timeSignature)]) + environLocal.printDebug([ + 'bad beat specification: ' + + f'{self.src} in a meter of {timeSignature}' + ]) post = 0.0 return post @@ -1164,11 +1166,13 @@ def tokenizeBody(self, lines): rtt = RTTagged(line) rtt.lineNumber = currentLineNumber post.append(rtt) - except Exception: + except Exception as exc: import traceback tracebackMessage = traceback.format_exc() - raise RTHandlerException('At line %s (%s) an exception was raised: \n%s' % ( - currentLineNumber, line, tracebackMessage)) + raise RTHandlerException( + f'At line {currentLineNumber} ({line}) an exception was raised:\n' + + f'{tracebackMessage}' + ) from exc return post def tokenizeAtoms(self, line, container=None): diff --git a/music21/romanText/translate.py b/music21/romanText/translate.py index dc858b10a4..2cb9526fd2 100644 --- a/music21/romanText/translate.py +++ b/music21/romanText/translate.py @@ -198,11 +198,12 @@ def _copySingleMeasure(rtTagged, p, kCurrent): if mPast.number == target: try: m = copy.deepcopy(mPast) - except TypeError: # pragma: no cover + except TypeError as te: # pragma: no cover raise RomanTextTranslateException( f'Failed to copy measure {mPast.number}:' + ' did you perhaps parse an RTOpus object with romanTextToStreamScore ' - + 'instead of romanTextToStreamOpus?') + + 'instead of romanTextToStreamOpus?' + ) from te m.number = rtTagged.number[0] # update all keys for rnPast in m.getElementsByClass(roman.RomanNumeral): @@ -263,13 +264,13 @@ def _copyMultipleMeasures(rtMeasure: rtObjects.RTMeasure, if mPast.number in range(targetStart, targetEnd + 1): try: m = copy.deepcopy(mPast) - except TypeError: # pragma: no cover + except TypeError as te: # pragma: no cover raise RomanTextTranslateException( - 'Failed to copy measure {0} to measure range {1}-{2}: '.format( - mPast.number, targetStart, targetEnd) - + 'did you perhaps parse an RTOpus object with romanTextToStreamScore ' - + 'instead of romanTextToStreamOpus?') - + f'Failed to copy measure {mPast.number} to measure range ' + + f'{targetStart}-{targetEnd}: did you perhaps parse an RTOpus ' + + 'object with romanTextToStreamScore instead of ' + + 'romanTextToStreamOpus?' + ) from te m.number = rtMeasure.number[0] + mPast.number - targetStart measures.append(m) # update all keys @@ -381,11 +382,11 @@ def translateTokens(self, tokens): for token in tokens: try: self.translateOneLineToken(token) - except Exception: + except Exception as exc: tracebackMessage = traceback.format_exc() raise RomanTextTranslateException( f'At line {token.lineNumber} for token {token}, ' - + f'an exception was raised: \n{tracebackMessage}') + + f'an exception was raised: \n{tracebackMessage}') from exc p = self.p p.coreElementsChanged() @@ -661,8 +662,8 @@ def parseKeySignatureTag(self, rtTagged: rtObjects.RTTagged): try: dataVal = int(data) self.keySigCurrent = key.KeySignature(dataVal) - except ValueError: - raise RomanTextTranslateException(f'Cannot parse key signature: {data!r}') + except ValueError as ve: + raise RomanTextTranslateException(f'Cannot parse key signature: {data!r}') from ve self.setKeySigFromFirstKeyToken = False # environLocal.printDebug(['keySigCurrent:', keySigCurrent]) self.foundAKeySignatureSoFar = True @@ -734,9 +735,10 @@ def translateSingleMeasureAtom( elif isinstance(a, rtObjects.RTKeySignature): try: # this sets the keysignature but not the prefix text thisSig = a.getKeySignature() - except (exceptions21.Music21Exception, ValueError): # pragma: no cover + except (exceptions21.Music21Exception, ValueError) as ve: # pragma: no cover raise RomanTextTranslateException( - f'cannot get key from {a.src} in line {self.currentMeasureToken.src}') + f'cannot get key from {a.src} in line {self.currentMeasureToken.src}' + ) from ve # insert at beginning of measure if at beginning # -- for things like pickups. if m.number <= 1: @@ -752,13 +754,12 @@ def translateSingleMeasureAtom( # set new offset based on beat try: newOffset = a.getOffset(self.tsCurrent) - except ValueError: # pragma: no cover + except ValueError as ve: # pragma: no cover raise RomanTextTranslateException( - 'cannot properly get an offset from ' - + f'beat data {a.src}' - + 'under timeSignature {0} in line {1}'.format( - self.tsCurrent, - self.currentMeasureToken.src)) + f'cannot properly get an offset from beat data {a.src} ' + f'under timeSignature {self.tsCurrent} ' + f'in line {self.currentMeasureToken.src}' + ) from ve if (self.previousChordInMeasure is None and self.previousRn is not None and newOffset > 0): @@ -932,9 +933,10 @@ def setAnalyticKey(self, a): try: # this sets the key and the keysignature self.kCurrent, pl = _getKeyAndPrefix(a) self.prefixLyric += pl - except (ValueError, exceptions21.Music21Exception): # pragma: no cover + except (ValueError, exceptions21.Music21Exception) as ve: # pragma: no cover raise RomanTextTranslateException( - f'cannot get analytic key from {a.src} in line {self.currentMeasureToken.src}') + f'cannot get analytic key from {a.src} in line {self.currentMeasureToken.src}' + ) from ve self.setKeyChangeToken = True diff --git a/music21/romanText/tsvConverter.py b/music21/romanText/tsvConverter.py index 814446122d..2444b1af6e 100644 --- a/music21/romanText/tsvConverter.py +++ b/music21/romanText/tsvConverter.py @@ -13,7 +13,6 @@ ''' from __future__ import annotations -import abc import csv import fractions import pathlib @@ -155,7 +154,7 @@ def _float_or_frac(value): DCML_HEADERS = {1: DCML_V1_HEADERS, 2: DCML_V2_HEADERS} -class TabChordBase(abc.ABC): +class TabChordBase(): ''' Abstract base class for intermediate representation format for moving between tabular data and music21 chords. diff --git a/music21/scale/__init__.py b/music21/scale/__init__.py index 80e81d0eaf..87cc34c749 100644 --- a/music21/scale/__init__.py +++ b/music21/scale/__init__.py @@ -353,7 +353,6 @@ def buildNetworkFromPitches(self, pitchList): for currentPitch, nextPitch in zip(pitchList, pitchList[1:]): intervalList.append(interval.Interval(currentPitch, nextPitch)) if pitchList[-1].name == pitchList[0].name: # the completion of the scale has been given. - # print('hi %s ' % pitchList) # this scale is only octave duplicating if the top note is exactly # 1 octave above the bottom; if it spans more than one octave, # all notes must be identical in each octave @@ -1753,12 +1752,6 @@ def pitchFromDegree( return post - # if 0 < degree <= self._abstract.getDegreeMaxUnique(): - # return self.getPitches()[degree - 1] - # else: - # raise('Scale degree is out of bounds: must be between 1 and %s.' % ( - # self._abstract.getDegreeMaxUnique())) - def pitchesFromScaleDegrees( self, degreeTargets, diff --git a/music21/scale/intervalNetwork.py b/music21/scale/intervalNetwork.py index 82a475b792..d36a704045 100644 --- a/music21/scale/intervalNetwork.py +++ b/music21/scale/intervalNetwork.py @@ -2201,7 +2201,7 @@ def realizeMinMax( # now find lowest and highest pitch minPitch = post[-1] maxPitch = post[0] - for p, nId in postPairs + prePairs: + for p, _nId in postPairs + prePairs: if p.ps < minPitch.ps: minPitch = p if p.ps > maxPitch.ps: diff --git a/music21/search/base.py b/music21/search/base.py index 0ddff09e88..a8946e41ce 100644 --- a/music21/search/base.py +++ b/music21/search/base.py @@ -525,7 +525,7 @@ def approximateNoteSearch(thisStream, otherStreams): >>> o3.id = 'o3' >>> l = search.approximateNoteSearch(s, [o1, o2, o3]) >>> for i in l: - ... print('%s %r' % (i.id, i.matchProbability)) + ... print(f'{i.id} {i.matchProbability!r}') o1 0.666666... o3 0.333333... o2 0.083333... @@ -561,7 +561,7 @@ def approximateNoteSearchNoRhythm(thisStream, otherStreams): >>> o3.id = 'o3' >>> l = search.approximateNoteSearchNoRhythm(s, [o1, o2, o3]) >>> for i in l: - ... print('%s %r' % (i.id, i.matchProbability)) + ... print(f'{i.id} {i.matchProbability!r}') o1 0.83333333... o3 0.5 o2 0.1666666... @@ -597,7 +597,7 @@ def approximateNoteSearchOnlyRhythm(thisStream, otherStreams): >>> o3.id = 'o3' >>> l = search.approximateNoteSearchOnlyRhythm(s, [o1, o2, o3]) >>> for i in l: - ... print('%s %r' % (i.id, i.matchProbability)) + ... print(f'{i.id} {i.matchProbability!r}') o1 0.5 o3 0.33... o2 0.0 @@ -635,7 +635,7 @@ def approximateNoteSearchWeighted(thisStream, otherStreams): >>> o4.id = 'o4' >>> l = search.approximateNoteSearchWeighted(s, [o1, o2, o3, o4]) >>> for i in l: - ... print('%s %r' % (i.id, i.matchProbability)) + ... print(f'{i.id} {i.matchProbability!r}') o3 0.83333... o1 0.75 o4 0.75 @@ -1068,10 +1068,18 @@ def mostCommonMeasureRhythms(streamIn, transposeDiatonic=False): >>> bach = corpus.parse('bwv1.6') >>> sortedRhythms = search.mostCommonMeasureRhythms(bach) >>> for in_dict in sortedRhythms[0:3]: - ... print(f"no: {in_dict['number']} rhythmString: {in_dict['rhythmString']}") - ... print('bars: %r' % ([(m.number, - ... str(m.getContextByClass(stream.Part).id)) - ... for m in in_dict['measures']])) + ... number = in_dict['number'] + ... rhythmString = in_dict['rhythmString'] + ... measures = in_dict['measures'] + ... print( + ... f'no: {number} ' + ... + f'rhythmString: {rhythmString}' + ... ) + ... bars = [ + ... (m.number, str(m.getContextByClass(stream.Part).id)) + ... for m in measures + ... ] + ... print(f'bars: {bars!r}') ... in_dict['rhythm'].show('text') ... print('-----') no: 34 rhythmString: PPPP diff --git a/music21/sieve.py b/music21/sieve.py index ec66a11e6c..d1b754ceb2 100644 --- a/music21/sieve.py +++ b/music21/sieve.py @@ -860,8 +860,10 @@ def __init__(self, src, z=None): # assign self._residuals and do analysis try: self._process() - except AssertionError: - raise CompressionSegmentException('no Residual classes found for this z range') + except AssertionError as assertError: + raise CompressionSegmentException( + 'no Residual classes found for this z range' + ) from assertError def _zUpdate(self, z=None): # z must at least be a superset of match diff --git a/music21/sites.py b/music21/sites.py index 309cfe37a1..1da83fcb3f 100644 --- a/music21/sites.py +++ b/music21/sites.py @@ -255,8 +255,6 @@ def __deepcopy__(self, memo=None): newIdKey = None else: newIdKey = id(newSite.site) - # if newIdKey != idKey and oldSite.site != None: - # print('Error! %s %s' % (newIdKey, idKey)) newSite.siteIndex = oldSite.siteIndex newSite.globalSiteIndex = _singletonCounter() newSite.classString = oldSite.classString @@ -357,7 +355,10 @@ def add(self, obj, timeValue=None, idKey=None, classString=None): updateNotAdd = True # if idKey is not None: - # print('Updating idKey %s for object %s' % (idKey, id(obj))) + # print( + # 'Updating idKey ' + # + f'{idKey} for object {id(obj)}' + # ) # environLocal.printDebug(['adding obj', obj, idKey]) # weak refs were being passed in __deepcopy__ calling this method @@ -663,7 +664,11 @@ def getObjByClass( priorityTarget=priorityTarget, excludeNone=True, ) # objs is a generator - # printMemo(memo, 'getObjByClass() called: looking at %s sites' % len(objs)) + # printMemo( + # memo, + # 'getObjByClass() called: looking at ' + # + f'{len(objs)} sites' + # ) classNameIsStr = isinstance(className, str) for obj in objs: # environLocal.printDebug(['memo', memo]) diff --git a/music21/spanner.py b/music21/spanner.py index d7e8afe030..fbf44aabfd 100644 --- a/music21/spanner.py +++ b/music21/spanner.py @@ -462,10 +462,12 @@ def addSpannedElements( else: pass # it makes sense to not have multiple copies - # environLocal.printDebug(['''attempting to add an object (%s) that is - # already found in the SpannerStorage stream of spanner %s; - # this may not be an error.''' % (c, self)]) - + # environLocal.printDebug([ + # 'attempting to add an object ' + # + f'({c}) that is already found in the SpannerStorage stream ' + # + f'of spanner {self};\n' + # + 'this may not be an error.' + # ]) self.spannerStorage.coreElementsChanged() def hasSpannedElement(self, spannedElement: base.Music21Object) -> bool: diff --git a/music21/stream/base.py b/music21/stream/base.py index c942b79776..2ddda531cd 100644 --- a/music21/stream/base.py +++ b/music21/stream/base.py @@ -668,11 +668,11 @@ def __getitem__(self, else: try: match = self.elements[k] - except IndexError: + except IndexError as ie: raise IndexError( f'attempting to access index {k} ' + f'while elements is of size {len(self.elements)}' - ) + ) from ie # setting active site as cautionary measure self.coreSelfActiveSite(match) return t.cast(M21ObjType, match) @@ -2185,10 +2185,10 @@ def elementOffset(self, element, returnSpecial=False): if isinstance(o, str) and returnSpecial is False and o in OffsetSpecial: try: return getattr(self, o) - except AttributeError: # pragma: no cover + except AttributeError as ae: # pragma: no cover raise base.SitesException( 'attempted to retrieve a bound offset with a string ' - + f'attribute that is not supported: {o}') + + f'attribute that is not supported: {o}') from ae else: return o @@ -2296,15 +2296,15 @@ def insert(self, try: activeSite = item.activeSite offset = item.getOffsetBySite(activeSite) - except AttributeError: + except AttributeError as ae: raise StreamException(f'Cannot insert item {item!r} to stream ' - + '-- is it a music21 object?') + + '-- is it a music21 object?') from ae # if not common.isNum(offset): try: # using float conversion instead of isNum for performance offset = float(offset) - except (ValueError, TypeError): - raise StreamException(f'Offset {offset!r} must be a number.') + except (ValueError, TypeError) as ve: + raise StreamException(f'Offset {offset!r} must be a number.') from ve element = item @@ -4318,9 +4318,9 @@ def hasMeasureNumberInformation(measureIterator: iterator.StreamIterator[Measure for m in measureIterator: try: mNumber = int(m.number) - except ValueError: # pragma: no cover + except ValueError as ve: # pragma: no cover # should never happen. - raise StreamException(f'found problematic measure for numbering: {m}') + raise StreamException(f'found problematic measure for numbering: {m}') from ve if mNumber != 0: return True return False @@ -5678,8 +5678,9 @@ def getTimeSignatures(self, *, # get a default and/or place default at zero if nothing at zero if returnDefault: if not post or post[0].offset > 0.0: - ts = meter.TimeSignature('%s/%s' % (defaults.meterNumerator, - defaults.meterDenominatorBeatType)) + ts = meter.TimeSignature( + f'{defaults.meterNumerator}/{defaults.meterDenominatorBeatType}' + ) post.insert(0, ts) # environLocal.printDebug(['getTimeSignatures(): final result:', post[0]]) return post @@ -5813,7 +5814,7 @@ def getInstrument(self, ) return post.first() - def invertDiatonic(self, inversionNote=note.Note('C4'), *, inPlace=False): + def invertDiatonic(self, inversionNote: note.Note|None = None, *, inPlace=False): ''' inverts a stream diatonically around the given note (by default, middle C) @@ -5872,6 +5873,7 @@ def invertDiatonic(self, inversionNote=note.Note('C4'), *, inPlace=False): * Changed in v5: inPlace is False by default. ''' + inversionNoteReal: note.Note = inversionNote or note.Note('C4') if inPlace: returnStream = self else: @@ -5888,7 +5890,7 @@ def invertDiatonic(self, inversionNote=note.Note('C4'), *, inPlace=False): ourKey = None # for might be undefined warning quickSearch = False - inversionDNN = inversionNote.pitch.diatonicNoteNum + inversionDNN = inversionNoteReal.pitch.diatonicNoteNum for n in returnStream[note.NotRest]: n.pitch.diatonicNoteNum = (2 * inversionDNN) - n.pitch.diatonicNoteNum if quickSearch: # use previously found @@ -6037,10 +6039,10 @@ def repeatAppend(self, item, numberOfTimes): unused = item.isStream element = item # if not isinstance(item, music21.Music21Object): - except AttributeError: + except AttributeError as ae: # element = music21.ElementWrapper(item) raise StreamException('to put a non Music21Object in a stream, ' - + 'create a music21.ElementWrapper for the item') + + 'create a music21.ElementWrapper for the item') from ae # # if not an element, embed # if not isinstance(item, music21.Music21Object): # element = music21.ElementWrapper(item) @@ -6072,11 +6074,11 @@ def repeatInsert(self, item, offsets): unused = item.isStream element = item # if not isinstance(item, music21.Music21Object): - except AttributeError: + except AttributeError as ae: # if not an element, embed # element = music21.ElementWrapper(item) raise StreamException('to put a non Music21Object in a stream, ' - + 'create a music21.ElementWrapper for the item') + + 'create a music21.ElementWrapper for the item') from ae # if not isinstance(item, music21.Music21Object): # # if not an element, embed # element = music21.ElementWrapper(item) @@ -7048,7 +7050,7 @@ def makeNotation(self, try: makeNotation.makeBeams(returnStream, inPlace=True) except meter.MeterException as me: - warnings.warn(str(me)) + warnings.warn(str(me), stacklevel=2) # note: this needs to be after makeBeams, as placing this before # makeBeams was causing the duration's tuplet to lose its type setting @@ -7698,7 +7700,7 @@ def sorted(self): False >>> g = '' >>> for myElement in s: - ... g += '%s: %s; ' % (myElement.offset, myElement.name) + ... g += f'{myElement.offset}: {myElement.name}; ' >>> g '0.0: C#; 2.0: C#; 4.0: C#; 1.0: D-; 3.0: D-; 5.0: D-; ' >>> y = s.sorted() @@ -7706,7 +7708,7 @@ def sorted(self): True >>> g = '' >>> for myElement in y: - ... g += '%s: %s; ' % (myElement.offset, myElement.name) + ... g += f'{myElement.offset}: {myElement.name}; ' >>> g '0.0: C#; 1.0: D-; 2.0: C#; 3.0: D-; 4.0: C#; 5.0: D-; ' >>> farRight = note.Note('E') @@ -7715,13 +7717,13 @@ def sorted(self): >>> y.insert(farRight) >>> g = '' >>> for myElement in y: - ... g += '%s: %s; ' % (myElement.offset, myElement.name) + ... g += f'{myElement.offset}: {myElement.name}; ' >>> g '0.0: C#; 1.0: D-; 2.0: C#; 3.0: D-; 4.0: C#; 5.0: D-; 2.0: E; ' >>> z = y.sorted() >>> g = '' >>> for myElement in z: - ... g += '%s: %s; ' % (myElement.offset, myElement.name) + ... g += f'{myElement.offset}: {myElement.name}; ' >>> g '0.0: C#; 1.0: D-; 2.0: C#; 2.0: E; 3.0: D-; 4.0: C#; 5.0: D-; ' >>> z[2].name, z[3].name @@ -7904,9 +7906,7 @@ def flatten(self, retainContainers=False) -> t.Self: >>> g = '' >>> for myElement in s: - ... g += '%s: %s; ' % (myElement.offset, myElement.name) - ... - + ... g += f'{myElement.offset}: {myElement.name}; ' >>> g '0.0: C#; 2.0: C#; 4.0: C#; 1.0: D-; 3.0: D-; 5.0: D-; ' @@ -7916,9 +7916,7 @@ def flatten(self, retainContainers=False) -> t.Self: >>> g = '' >>> for myElement in y: - ... g += '%s: %s; ' % (myElement.offset, myElement.name) - ... - + ... g += f'{myElement.offset}: {myElement.name}; ' >>> g '0.0: C#; 1.0: D-; 2.0: C#; 3.0: D-; 4.0: C#; 5.0: D-; ' @@ -8577,10 +8575,8 @@ def _getSeconds(self): mm = ti.getSoundingMetronomeMark() offsetMetronomeMarkPairs.append([o, mm]) - for i, (o, mm) in enumerate(offsetMetronomeMarkPairs): - if i == 0 and o > 0.0: - getTempoFromContext = True - break # just need first + if len(offsetMetronomeMarkPairs) and offsetMetronomeMarkPairs[0][0] > 0.0: + getTempoFromContext = True if getTempoFromContext: ti = self.getContextByClass('TempoIndication') @@ -8717,10 +8713,9 @@ def metronomeMarkBoundaries(self, srcObj=None): offsetPairs[0][1])) # add any remaining ranges, starting from the second; if last, # use the highest time as the boundary - for i, (o, mm) in enumerate(offsetPairs): - if i == 0: - continue # already added first - elif i == len(offsetPairs) - 1: # last index + for i in range(1, len(offsetPairs)): + # start at 1 since we have already added first + if i == len(offsetPairs) - 1: # last index mmBoundaries.append((offsetPairs[i][0], highestTime, offsetPairs[i][1])) else: # add with next boundary @@ -8978,9 +8973,10 @@ def beatAndMeasureFromOffset(self, searchOffset, fixZeros=True): 'beatAndMeasureFromOffset: could not find a time signature for that place.') try: myBeat = ts1.getBeatProportion(searchOffset - myMeas.offset) - except (ValueError, IndexError, AttributeError, exceptions21.Music21Exception): + except (ValueError, IndexError, AttributeError, exceptions21.Music21Exception) as exc: raise StreamException( - 'beatAndMeasureFromOffset: offset is beyond the end of the piece') + 'beatAndMeasureFromOffset: offset is beyond the end of the piece' + ) from exc foundMeasureNumber = myMeas.number # deal with second half of partial measures @@ -9639,8 +9635,9 @@ def sliceByQuarterLengths(self, quarterLengthList, *, target=None, if not opFrac(sum(qlProcess)) == e.quarterLength: raise StreamException( - 'cannot map quarterLength list into element Duration: %s, %s' % ( - sum(qlProcess), e.quarterLength)) + 'cannot map quarterLength list into element Duration: ' + + f'{sum(qlProcess)}, {e.quarterLength}' + ) post = e.splitByQuarterLengths(qlProcess, addTies=addTies) # remove e from the source diff --git a/music21/stream/core.py b/music21/stream/core.py index 0dc3019f5a..4570ad3362 100644 --- a/music21/stream/core.py +++ b/music21/stream/core.py @@ -194,9 +194,9 @@ def coreSetElementOffset( try: # try first, for the general case of not OffsetSpecial. offset = opFrac(offset) # type: ignore - except TypeError: + except TypeError as te: if offset not in OffsetSpecial: # pragma: no cover - raise StreamException(f'Cannot set offset to {offset!r} for {element}') + raise StreamException(f'Cannot set offset to {offset!r} for {element}') from te idEl = id(element) if not addElement and idEl not in self._offsetDict: diff --git a/music21/stream/filters.py b/music21/stream/filters.py index 296f3854f5..473284b81c 100644 --- a/music21/stream/filters.py +++ b/music21/stream/filters.py @@ -133,7 +133,7 @@ def reset(self): def __call__(self, item, iterator=None): if self.numToFind == 0: # short circuit -- we already have - raise StopIteration + raise StopIteration() if item in self.target: # would popping the item be faster? No: then can't use for IsNotFilter @@ -415,7 +415,7 @@ def isElementOffsetInRange(self, e, offset, *, stopAfterEnd=False) -> bool: if stopAfterEnd: # if sorted, optimize by breaking after exceeding offsetEnd # eventually we could do a binary search to speed up - raise StopIteration + raise StopIteration() return False dur = e.duration diff --git a/music21/stream/iterator.py b/music21/stream/iterator.py index 5318f2291d..6040ab8275 100644 --- a/music21/stream/iterator.py +++ b/music21/stream/iterator.py @@ -215,7 +215,7 @@ def __next__(self) -> M21ObjType: return e self.cleanup() - raise StopIteration + raise StopIteration() def __getattr__(self, attr): ''' @@ -1575,7 +1575,7 @@ def __init__(self, def __next__(self) -> list[M21ObjType]: # type: ignore if self.raiseStopIterationNext: - raise StopIteration + raise StopIteration() retElementList: list[M21ObjType] = [] # make sure that cleanup is not called during the loop @@ -1602,13 +1602,13 @@ def __next__(self) -> list[M21ObjType]: # type: ignore self.activeInformation['lastYielded'] = retElementList[0] return retElementList - except StopIteration: # from the while statement. + except StopIteration as parent_stop: # from the while statement. if retElementList: self.raiseStopIterationNext = True self.activeInformation['lastYielded'] = retElementList[0] return retElementList else: - raise StopIteration + raise StopIteration() from parent_stop def reset(self): ''' @@ -1855,7 +1855,7 @@ def __next__(self) -> M21ObjType: self.activeInformation['lastYielded'] = None # always clean this up, no matter what self.cleanup() - raise StopIteration + raise StopIteration() def reset(self): ''' diff --git a/music21/stream/makeNotation.py b/music21/stream/makeNotation.py index 693ae55f92..f3407bb2a7 100644 --- a/music21/stream/makeNotation.py +++ b/music21/stream/makeNotation.py @@ -195,9 +195,10 @@ def makeBeams( if durSum > barQL: # environLocal.printDebug([ - # 'attempting makeBeams with a bar that contains durations - # that sum greater than bar duration (%s > %s)' % - # (durSum, barQL)]) + # 'attempting makeBeams with a bar that contains durations ' + # + 'that sum greater than bar duration ' + # + f'({durSum} > {barQL})' + # ]) continue # getBeams @@ -1304,8 +1305,10 @@ def makeTies( continue # skip elements that begin past measure boundary. # TODO: put them entirely in the next measure. # raise stream.StreamException( - # 'element (%s) has offset %s within a measure ' - # 'that ends at offset %s' % (e, eOffset, mEnd)) + # 'element ' + # + f'({e}) has offset {eOffset} within a measure ' + # + f'that ends at offset {mEnd}' + # ) qLenWithinMeasure = mEnd - eOffset e, eRemain = e.splitAtQuarterLength( diff --git a/music21/style.py b/music21/style.py index a558df407f..92901c3497 100644 --- a/music21/style.py +++ b/music21/style.py @@ -457,7 +457,7 @@ def _setSize(self, value): value = common.numToIntOrFloat(value) except ValueError: pass # MusicXML font sizes can be CSS strings. - # raise TextFormatException('Not a supported size: %s' % value) + # raise TextFormatException(f'Not a supported size: {value}') self._fontSize = value fontSize = property(_getSize, @@ -653,11 +653,8 @@ def hasStyleInformation(self) -> bool: >>> lObj.hasStyleInformation True ''' - try: - self._style - except AttributeError: - pass - + if not hasattr(self, '_style'): + return False return self._style is not None @property diff --git a/music21/tempo.py b/music21/tempo.py index 3d51e260e7..e51560351a 100644 --- a/music21/tempo.py +++ b/music21/tempo.py @@ -1259,7 +1259,8 @@ def interpolateElements(element1, element2, sourceStream, >>> destStream2.insert(50.5, element2) >>> tempo.interpolateElements(element1, element2, sourceStream, destStream2) >>> for el in [eA, eB, eC]: - ... print('%.1f' % (el.getOffsetBySite(destStream2),)) + ... offset = el.getOffsetBySite(destStream2) + ... print(f'{offset:.1f}') 20.2 30.3 40.4 diff --git a/music21/test/memoryUsage.py b/music21/test/memoryUsage.py index 1159cb7d11..816609476a 100644 --- a/music21/test/memoryUsage.py +++ b/music21/test/memoryUsage.py @@ -7,8 +7,8 @@ try: # noinspection PyPackageRequirements import guppy # type: ignore - except ImportError: - raise exceptions21.Music21Exception('memoryUsage.py requires guppy') + except ImportError as ie: + raise exceptions21.Music21Exception('memoryUsage.py requires guppy') from ie hp = guppy.hpy() hp.setrelheap() diff --git a/music21/test/multiprocessTest.py b/music21/test/multiprocessTest.py index 65804e9062..8ab58ccb9f 100644 --- a/music21/test/multiprocessTest.py +++ b/music21/test/multiprocessTest.py @@ -243,13 +243,16 @@ def printSummary(summaryOutput, timeStart, pathsToRun): elif moduleResponse.returnCode == 'UntrappedException': otherSummary.append(f'Untrapped Exception for unknown module: {moduleResponse.fp}') elif moduleResponse.returnCode == 'TrappedException': - otherSummary.append('Trapped Exception for module %s, at %s: %s' % - (moduleResponse.moduleName, - moduleResponse.fp, - moduleResponse.testRunner)) + otherSummary.append( + f'Trapped Exception for module {moduleResponse.moduleName}, ' + + f'at {moduleResponse.fp}: ' + + f'{moduleResponse.testRunner}' + ) elif moduleResponse.returnCode == 'LargeException': - otherSummary.append('Large Exception for file %s: %s' % - (moduleResponse.fp, moduleResponse.testResult)) + otherSummary.append( + f'Large Exception for file {moduleResponse.fp}: ' + + f'{moduleResponse.testResult}' + ) elif moduleResponse.returnCode == 'ImportError': otherSummary.append(f'Import Error for {moduleResponse.fp}') elif moduleResponse.returnCode == 'NotInTree': @@ -258,33 +261,30 @@ def printSummary(summaryOutput, timeStart, pathsToRun): elif moduleResponse.returnCode == 'TestsRun': totalTests += moduleResponse.testsRun if moduleResponse.success: - successSummary.append('%s successfully ran %s tests in %s seconds' - % (moduleResponse.moduleName, - moduleResponse.testsRun, - moduleResponse.runTime)) + successSummary.append( + f'{moduleResponse.moduleName} successfully ran ' + + f'{moduleResponse.testsRun} tests in ' + + f'{moduleResponse.runTime} seconds' + ) else: errorsList = moduleResponse.errors # not the original errors list! see pickle note above failuresList = moduleResponse.failures errorsFoundSummary.append( '\n-----------------------------\n' - + '%s had %s ERRORS and %s FAILURES in %s tests after %s seconds:\n' % - (moduleResponse.moduleName, len(errorsList), - len(failuresList), moduleResponse.testsRun, moduleResponse.runTime) - + '-----------------------------\n') - + + f'{moduleResponse.moduleName} had ' + + f'{len(errorsList)} ERRORS and ' + + f'{len(failuresList)} FAILURES in ' + + f'{moduleResponse.testsRun} tests after ' + + f'{moduleResponse.runTime} seconds:\n' + + '-----------------------------\n' + ) for e in errorsList: outStr += e + '\n' errorsFoundSummary.append(str(e)) for f in failuresList: outStr += f + '\n' errorsFoundSummary.append(str(f)) - # for e in errorsList: - # print(e[0], e[1]) - # errorsFoundSummary.append('%s: %s' % (e[0], e[1])) - # for f in failuresList: - # print(f[0], f[1]) - # errorsFoundSummary.append('%s: %s' % (f[0], f[1])) else: otherSummary.append(f'Unknown return code {moduleResponse}') diff --git a/music21/test/test_base.py b/music21/test/test_base.py index 070a345567..34d8d83a2c 100644 --- a/music21/test/test_base.py +++ b/music21/test/test_base.py @@ -459,7 +459,7 @@ def testPickupMeasuresBuilt(self): self.assertEqual(m2.duration.quarterLength, 4.0) # we cannot get a bar duration b/c we have not associated a ts try: - m2.barDuration.quarterLength + m2.barDuration.quarterLength # noqa: B018 (useless expression) except exceptions21.StreamException: pass diff --git a/music21/test/treeYield.py b/music21/test/treeYield.py index b24691360b..bd32765863 100644 --- a/music21/test/treeYield.py +++ b/music21/test/treeYield.py @@ -93,8 +93,10 @@ def run(self, obj, memo=None): self.stackVals.append(objTuple) try: yield from self.run(gotValue, memo=memo) - except RuntimeError: - raise ValueError(f'Maximum recursion on:\n{self.currentLevel()}') + except RuntimeError as runError: + raise ValueError( + f'Maximum recursion on:\n{self.currentLevel()}' + ) from runError self.stackVals.pop() self.currentStack.pop() diff --git a/music21/tree/timespanTree.py b/music21/tree/timespanTree.py index 0065a3f784..905b15605d 100644 --- a/music21/tree/timespanTree.py +++ b/music21/tree/timespanTree.py @@ -196,8 +196,7 @@ def index(self, span): >>> tsTree.insert(ts) >>> for timespan in ts: - ... print("%r %s" % (timespan, tsTree.index(timespan))) - ... + ... print(f'{timespan!r} {tsTree.index(timespan)}') 0 1 2 @@ -651,8 +650,7 @@ def splitAt(self, offsets): () >>> for timespan in scoreTree.elementsOverlappingOffset(0.1): - ... print("%r, %s" % (timespan, timespan.part.id)) - ... + ... print(f'{timespan!r}, {timespan.part.id}') >, Soprano >, Tenor >, Bass @@ -663,8 +661,7 @@ def splitAt(self, offsets): >>> scoreTree.splitAt(0.1) >>> for timespan in scoreTree.elementsStartingAt(0.1): - ... print("%r, %s" % (timespan, timespan.part.id)) - ... + ... print(f'{timespan!r}, {timespan.part.id}') >, Soprano >, Tenor >, Bass @@ -718,7 +715,7 @@ def unwrapVerticalities(verticalities): ... print(part) ... horizontality = unwrapped[part] ... for timespan in horizontality: - ... print('\t%r' % timespan) + ... print(f'\t{timespan!r}') ... > diff --git a/music21/tree/trees.py b/music21/tree/trees.py index 47ae1321ef..840f4553ee 100644 --- a/music21/tree/trees.py +++ b/music21/tree/trees.py @@ -926,8 +926,10 @@ def __contains__(self, element): ''' try: offset = element.offset - except AttributeError: - raise ElementTreeException('element must be a Music21Object, i.e., must have offset') + except AttributeError as ae: + raise ElementTreeException( + 'element must be a Music21Object, i.e., must have offset' + ) from ae candidates = self.elementsStartingAt(offset) if element in candidates: return True diff --git a/music21/voiceLeading.py b/music21/voiceLeading.py index 95d3787ebc..30b0b405b0 100644 --- a/music21/voiceLeading.py +++ b/music21/voiceLeading.py @@ -202,11 +202,11 @@ def key(self, keyValue): isKey = (isinstance(keyValue, key.Key)) if isKey is False: raise AttributeError - except AttributeError: # pragma: no cover + except AttributeError as ae: # pragma: no cover raise VoiceLeadingQuartetException( 'got a key signature that is not a string or music21 Key ' + f'object: {keyValue}' - ) + ) from ae self._key = keyValue def _setVoiceNote( @@ -1979,7 +1979,7 @@ def _getMelodicIntervals(self): tempListOne = self.noteList[:-1] tempListTwo = self.noteList[1:] melodicIntervalList = [] - for n1, n2 in zip(tempListOne, tempListTwo): + for n1, n2 in zip(tempListOne, tempListTwo, strict=True): if n1 and n2: melodicIntervalList.append(interval.Interval(n1, n2)) else: @@ -2355,7 +2355,7 @@ def __init__(self, chordList=(), **keywords): self._chordList.append(value) # else: # raise NChordLinearSegmentException( - # 'not a valid chord specification: %s' % value) + # f'not a valid chord specification: {value}') except AttributeError as e: # pragma: no cover raise NChordLinearSegmentException( f'not a valid chord specification: {value!r}' diff --git a/pyproject.toml b/pyproject.toml index 0ca8f78845..4a5ab721e1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -75,8 +75,8 @@ include = [ line-length = 100 [tool.ruff.lint] -# Flake8 core (pycodestyle + pyflakes) + flake8-quotes -select = ['E', 'Q', 'F'] +# Flake8, pycodestyle, flake8-quotes + pyflakes +select = ['E', 'W', 'Q', 'F', 'B'] dummy-variable-rgx = "^(_.*|unused.*|i|j|counter|junk|dummy)" @@ -93,6 +93,8 @@ ignore = [ 'E303', # do not assign lambda -- okay by me. 'E731', + # zip without strict= ... nice to turn this off someday, when code more mature + 'B905', ] [tool.ruff.lint.per-file-ignores] From 46a8fe6bab9edcfd9e963768ae32e9bb91589aee Mon Sep 17 00:00:00 2001 From: Michael Scott Asato Cuthbert Date: Fri, 2 Jan 2026 17:01:24 -1000 Subject: [PATCH 05/13] fix bugs --- music21/audioSearch/scoreFollower.py | 2 +- music21/musicxml/m21ToXml.py | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/music21/audioSearch/scoreFollower.py b/music21/audioSearch/scoreFollower.py index fd5c63222d..cad65c7928 100644 --- a/music21/audioSearch/scoreFollower.py +++ b/music21/audioSearch/scoreFollower.py @@ -126,7 +126,7 @@ def repeatTranscription(self): # print('WE STAY AT:',) # print(self.lastNotePosition, len(self.scoreNotesOnly),) - # print(f'en percent {self.lastNotePosition * 100 / len(self.scoreNotesOnly}%') + # print(f'en percent {self.lastNotePosition * 100 / len(self.scoreNotesOnly)}%') # print(' this search begins at: ', self.startSearchAtSlot,) # print(f'countdown {self.countdown}') # print('Measure last note', self.scoreStream[self.lastNotePosition].measureNumber) diff --git a/music21/musicxml/m21ToXml.py b/music21/musicxml/m21ToXml.py index e9ccfc53f7..3d650e08ca 100644 --- a/music21/musicxml/m21ToXml.py +++ b/music21/musicxml/m21ToXml.py @@ -2868,9 +2868,7 @@ def fixupNotationMeasured(self): try: part.makeBeams(inPlace=True) except exceptions21.StreamException as se: # no measures or no time sig? - # incorrectly flagging MusicXMLWarning as not a Warning - # noinspection PyTypeChecker - warnings.warn(MusicXMLWarning, str(se), stacklevel=2) + warnings.warn(MusicXMLWarning(se), stacklevel=2) if not part.streamStatus.tuplets: for m in measures: for m_or_v in [m, *m.voices]: From 558f5137cb8406accb79d9e285f4bde3341b08fa Mon Sep 17 00:00:00 2001 From: Michael Scott Asato Cuthbert Date: Fri, 2 Jan 2026 17:07:42 -1000 Subject: [PATCH 06/13] fix broken tests --- documentation/docbuild/documenters.py | 12 +++++++----- music21/analysis/pitchAnalysis.py | 4 ++-- music21/metadata/__init__.py | 20 ++++++++++++++++++++ music21/tablature.py | 8 ++++---- 4 files changed, 33 insertions(+), 11 deletions(-) diff --git a/documentation/docbuild/documenters.py b/documentation/docbuild/documenters.py index 4baf0400bc..6f980c3331 100644 --- a/documentation/docbuild/documenters.py +++ b/documentation/docbuild/documenters.py @@ -538,8 +538,11 @@ def _formatInheritedMembersMapping(self, mapping, banner): for classDocumenter in self.baseClassDocumenters: if classDocumenter not in mapping: continue - result.append(banner.format( - classDocumenter.rstCrossReferenceString)) + result.append( + banner.format( + classDocumenter.rstCrossReferenceString + ) + ) result.append('') memberDocumenters = mapping[classDocumenter] result.append('.. hlist::') @@ -757,10 +760,9 @@ def inheritedReadwritePropertiesMapping(self): >>> mapping = documenter.inheritedReadwritePropertiesMapping >>> sortBy = lambda x: x.referentPackageSystemPath >>> for classDocumenter in sorted(mapping, key=sortBy): - ... print('{0}:'.format(classDocumenter.referentPackageSystemPath)) + ... print(f'{classDocumenter.referentPackageSystemPath}:') ... for attributeDocumenter in mapping[classDocumenter][:10]: - ... print('- {0}'.format(attributeDocumenter.referentPackageSystemPath)) - ... + ... print(f'- {attributeDocumenter.referentPackageSystemPath}') music21.base.Music21Object: - music21.base.Music21Object.activeSite - music21.base.Music21Object.derivation diff --git a/music21/analysis/pitchAnalysis.py b/music21/analysis/pitchAnalysis.py index bcbda27e05..c1352b6b64 100644 --- a/music21/analysis/pitchAnalysis.py +++ b/music21/analysis/pitchAnalysis.py @@ -36,7 +36,7 @@ def pitchAttributeCount(s, pitchAttr='name'): >>> nameCount = analysis.pitchAnalysis.pitchAttributeCount(bach, 'name') >>> for n, count in nameCount.most_common(3): - ... print(f'{n:2s}: {nameCount[n]:2d}') + ... print(f'{n:>2s}: {nameCount[n]:2d}') D: 26 A: 17 F#: 15 @@ -44,7 +44,7 @@ def pitchAttributeCount(s, pitchAttr='name'): >>> nameOctaveCount = analysis.pitchAnalysis.pitchAttributeCount(bach, 'nameWithOctave') >>> for n in sorted(nameOctaveCount): - ... print(f'{n:3s}: {nameOctaveCount[n]:2d}') + ... print(f'{n:>3s}: {nameOctaveCount[n]:2d}') A2: 2 A3: 5 A4: 10 diff --git a/music21/metadata/__init__.py b/music21/metadata/__init__.py index 49469f9431..7e85b67666 100755 --- a/music21/metadata/__init__.py +++ b/music21/metadata/__init__.py @@ -134,6 +134,21 @@ 'Metadata', 'RichMetadata', + 'Contributor', + 'Copyright', + 'Creator', + 'Date', + 'DateBetween', + 'DatePrimitive', + 'DateRelative', + 'DateSelection', + 'DateSingle', + 'Imprint', + 'Text', + 'ValueType', + + 'PropertyDescription', + 'bundles', 'caching', 'primitives', @@ -161,9 +176,14 @@ from music21.metadata.primitives import ( Contributor, Copyright, + Creator, Date, + DateBetween, DatePrimitive, + DateRelative, + DateSelection, DateSingle, + Imprint, Text, ValueType, ) diff --git a/music21/tablature.py b/music21/tablature.py index 2c019b4252..97189a2038 100644 --- a/music21/tablature.py +++ b/music21/tablature.py @@ -227,10 +227,10 @@ def getPitches(self) -> list[None|pitch.Pitch]: ''' if len(self.tuning) != self.numStrings: raise TablatureException( - 'Tuning must be set first, tuned for {0} notes, on a {1} string instrument'.format( - len(self.tuning), - self.numStrings - )) + 'Tuning must be set first, tuned for ' + + f'{len(self.tuning)} notes, on a ' + + f'{self.numStrings} string instrument' + ) pitchList: list[pitch.Pitch|None] = [None] * self.numStrings From bdb1bc45ae9ceb331c484db81996ca37d84eae39 Mon Sep 17 00:00:00 2001 From: Michael Scott Asato Cuthbert Date: Fri, 2 Jan 2026 17:20:39 -1000 Subject: [PATCH 07/13] format --- documentation/docbuild/documenters.py | 22 +++++++-------- music21/base.py | 9 ++++--- music21/beam.py | 5 ++-- music21/environment.py | 6 ++--- music21/metadata/caching.py | 39 ++++++++++++++------------- 5 files changed, 42 insertions(+), 39 deletions(-) diff --git a/documentation/docbuild/documenters.py b/documentation/docbuild/documenters.py index 6f980c3331..efd856e060 100644 --- a/documentation/docbuild/documenters.py +++ b/documentation/docbuild/documenters.py @@ -942,13 +942,10 @@ def rstInheritedDocAttrFormat(self): result.append('.. hlist::') result.append(' :columns: 3') result.append('') - formatString = ' - :attr:`~{0}.{1}`' + basePath = baseDocumenter.referentPackageSystemPath for attrName in attrNames: result.append( - formatString.format( - baseDocumenter.referentPackageSystemPath, - attrName, - ) + f' - :attr:`~{basePath}.{attrName}`' ) result.append('') return result @@ -1596,14 +1593,15 @@ def getRstComposerWorksFormat(self, corpusWork): # def getRstVirtualWorkFileDictFormat(self, corpusFile): # result = [] - # result.append('- {0} *({1})*: `{2}`'.format( - # str(corpusFile.title), - # str(corpusFile.format), - # str(corpusFile.path), - # )) + # result.append( + # f'- {corpusFile.title} ' + # f'*({corpusFile.format})*: ' + # f'`{corpusFile.path}`' + # ) # result.append('') - # result.append(' Source: {0}'.format( - # str(corpusFile.url))) + # result.append( + # f' Source: {corpusFile.url}' + # ) # result.append('') # return result diff --git a/music21/base.py b/music21/base.py index b6969d46b6..e4f65ca503 100644 --- a/music21/base.py +++ b/music21/base.py @@ -2127,10 +2127,11 @@ def contextSites( hypotheticalPosition = positionInStream.modify(offset=inStreamOffset) if topLevel not in memo: - # environLocal.printDebug('Yielding {}, {}, {} from contextSites'.format( - # topLevel, - # inStreamPos.shortRepr(), - # recurType)) + # environLocal.printDebug( + # f'Yielding {topLevel}, ' + # f'{inStreamPos.shortRepr()}, ' + # f'{recurType} from contextSites' + # ) if returnSortTuples: yield ContextSortTuple(topLevel, hypotheticalPosition, recurType) else: diff --git a/music21/beam.py b/music21/beam.py index 21b659c3e3..b2971aa530 100644 --- a/music21/beam.py +++ b/music21/beam.py @@ -367,8 +367,9 @@ def mergeConnectingPartialBeams(beamsList): continue if nextBeam.type in ('continue', 'stop'): environLocal.warn( - 'Found a messed up beam pair {}, {}, at index {} of \n{}'.format( - bThis, bNext, i, beamsList)) + f'Found a messed up beam pair {bThis}, {bNext}, ' + f'at index {i} of \n{beamsList}' + ) continue thisBeam.type = 'start' diff --git a/music21/environment.py b/music21/environment.py index e2ce9d0bb0..2a1ff11075 100644 --- a/music21/environment.py +++ b/music21/environment.py @@ -613,9 +613,9 @@ def getRootTempDir(self): if not refDir.exists(): raise EnvironmentException( - 'user-specified scratch directory ({!s}) does not exist; ' - 'remove preference file or reset Environment'.format( - refDir)) + f'user-specified scratch directory ({refDir!s}) does not exist; ' + f'remove preference file or reset Environment' + ) return refDir def getSettingsPath(self): diff --git a/music21/metadata/caching.py b/music21/metadata/caching.py index 33b3f4bd8b..4e4b9f23bc 100644 --- a/music21/metadata/caching.py +++ b/music21/metadata/caching.py @@ -157,8 +157,8 @@ def parseNonOpus(self, parsedObject): else: environLocal.printDebug( 'addFromPaths: got stream without metadata, ' - 'creating stub: {0}'.format( - common.relativepath(str(self.cleanFilePath)))) + + f'creating stub: {common.relativepath(str(self.cleanFilePath))}' + ) metadataEntry = metadata.bundles.MetadataEntry( sourcePath=self.cleanFilePath, metadataPayload=None, @@ -166,8 +166,10 @@ def parseNonOpus(self, parsedObject): ) self.results.append(metadataEntry) except Exception: # wide catch is fine. pylint: disable=broad-exception-caught - environLocal.warn('Had a problem with extracting metadata ' - 'for {0}, piece ignored'.format(self.filePath)) + environLocal.warn( + 'Had a problem with extracting metadata ' + + f'for {self.filePath}, piece ignored' + ) environLocal.warn(traceback.format_exc()) def parseOpus(self, parsedObject): @@ -182,9 +184,10 @@ def parseOpus(self, parsedObject): del score # for memory conservation except Exception as exception: # wide catch is fine. pylint: disable=broad-exception-caught environLocal.warn( - 'Had a problem with extracting metadata for score {0} ' - 'in {1}, whole opus ignored: {2}'.format( - scoreNumber, self.filePath, str(exception))) + 'Had a problem with extracting metadata for score ' + + f'{scoreNumber} in {self.filePath}, whole opus ignored: ' + + f'{exception}' + ) environLocal.printDebug(traceback.format_exc()) # Create a dummy metadata entry, representing the entire opus. # This lets the metadata bundle know it has already processed this @@ -208,8 +211,9 @@ def parseScoreInsideOpus(self, score, scoreNumber): if score.metadata is None or score.metadata.number is None: environLocal.printDebug( 'addFromPaths: got Opus that contains ' - 'Streams that do not have work numbers: ' - '{0}'.format(self.filePath)) + + 'Streams that do not have work numbers: ' + + str(self.filePath) + ) else: # update path to include work number corpusPath = metadata.bundles.MetadataBundle.corpusPathToKey( @@ -226,10 +230,9 @@ def parseScoreInsideOpus(self, score, scoreNumber): self.results.append(metadataEntry) except Exception as exception: # pylint: disable=broad-exception-caught environLocal.warn( - 'Had a problem with extracting metadata ' - 'for score {0} in {1}, whole opus ignored: ' - '{2}'.format( - scoreNumber, self.filePath, str(exception))) + f'Had a problem with extracting metadata for score {scoreNumber} ' + f'in {self.filePath}, whole opus ignored: {exception}' + ) environLocal.printDebug(traceback.format_exc()) # PUBLIC METHODS # @@ -294,11 +297,11 @@ def _report(totalJobs, remainingJobs, filePath, filePathErrorCount): ''' Report on the current job status. ''' - message = 'updated {0} of {1} files; total errors: {2} ... last file: {3}'.format( - totalJobs - remainingJobs, - totalJobs, - filePathErrorCount, - filePath, + completedJobs = totalJobs - remainingJobs + message = ( + f'updated {completedJobs} of {totalJobs} files; ' + f'total errors: {filePathErrorCount} ... ' + f'last file: {filePath}' ) return message From 6a52496825cfc779834b9b86910f571610d4f493 Mon Sep 17 00:00:00 2001 From: Michael Scott Asato Cuthbert Date: Fri, 2 Jan 2026 17:31:13 -1000 Subject: [PATCH 08/13] ruff passes! --- music21/base.py | 6 ++--- music21/chord/tables.py | 2 +- music21/common/objects.py | 2 +- music21/figuredBass/checker.py | 14 ++++------- music21/figuredBass/possibility.py | 3 ++- music21/figuredBass/realizer.py | 2 +- music21/graph/findPlot.py | 2 +- music21/graph/primitives.py | 2 +- music21/metadata/__init__.py | 38 +++++++++++++++--------------- music21/metadata/caching.py | 2 +- music21/midi/translate.py | 4 ++-- music21/musicxml/xmlToM21.py | 5 +++- music21/stream/base.py | 17 ++++++++----- pyproject.toml | 2 ++ 14 files changed, 53 insertions(+), 48 deletions(-) diff --git a/music21/base.py b/music21/base.py index e4f65ca503..6bcdae4809 100644 --- a/music21/base.py +++ b/music21/base.py @@ -638,8 +638,8 @@ def _deepcopySubclassable(self, ignoreAttributes = ignoreAttributes | defaultIgnoreSet new = common.defaultDeepcopy(self, memo, ignoreAttributes=ignoreAttributes) - setattr(new, '_cache', {}) - setattr(new, '_sites', Sites()) + new._cache = {} + new._sites = Sites() if 'groups' in defaultIgnoreSet: new.groups = Groups() @@ -648,7 +648,7 @@ def _deepcopySubclassable(self, newDerivation = Derivation(client=new) newDerivation.origin = self newDerivation.method = '__deepcopy__' - setattr(new, '_derivation', newDerivation) + new._derivation = newDerivation # None activeSite is correct for new value # must do this after copying diff --git a/music21/chord/tables.py b/music21/chord/tables.py index 0cc4e84031..1508fc47b9 100644 --- a/music21/chord/tables.py +++ b/music21/chord/tables.py @@ -1945,7 +1945,7 @@ def testForteNumberWithInversionToTnIndex(self): else: partition[key[0]].append(value) # append unique ids - for key, value in partition.items(): + for value in partition.values(): # the length of the list should be the max value stored self.assertEqual(max(value), len(value)) diff --git a/music21/common/objects.py b/music21/common/objects.py index bd169fa697..5735117633 100644 --- a/music21/common/objects.py +++ b/music21/common/objects.py @@ -193,7 +193,7 @@ class SlottedObjectMixin: def __getstate__(self): if getattr(self, '__dict__', None) is not None: - state = getattr(self, '__dict__').copy() + state = self.__dict__.copy() else: state = {} slots = self._getSlotsRecursive() diff --git a/music21/figuredBass/checker.py b/music21/figuredBass/checker.py index 76d8159d5e..2c8bb80869 100644 --- a/music21/figuredBass/checker.py +++ b/music21/figuredBass/checker.py @@ -369,18 +369,12 @@ def voiceCrossing(possibA): ''' partViolations = [] for part1Index in range(len(possibA)): - try: # noqa - higherPitch = possibA[part1Index] - # noinspection PyStatementEffect - higherPitch.ps # pylint: disable=pointless-statement - except AttributeError: + higherPitch = possibA[part1Index] + if not hasattr(higherPitch, 'ps'): continue for part2Index in range(part1Index + 1, len(possibA)): - try: # noqa - lowerPitch = possibA[part2Index] - # noinspection PyStatementEffect - lowerPitch.ps # pylint: disable=pointless-statement - except AttributeError: + lowerPitch = possibA[part2Index] + if not hasattr(lowerPitch, 'ps'): continue if higherPitch < lowerPitch: partViolations.append((part1Index + 1, part2Index + 1)) diff --git a/music21/figuredBass/possibility.py b/music21/figuredBass/possibility.py index e116bab33d..3f8c30d9c6 100644 --- a/music21/figuredBass/possibility.py +++ b/music21/figuredBass/possibility.py @@ -198,8 +198,9 @@ def upperPartsWithinLimit(possibA, maxSemitoneSeparation=12): return areUpperPartsWithinLimit +DEFAULT_MAX_PITCH = pitch.Pitch('B5') -def pitchesWithinLimit(possibA, maxPitch=pitch.Pitch('B5')): +def pitchesWithinLimit(possibA, maxPitch=DEFAULT_MAX_PITCH): ''' Returns True if all pitches in possibA are less than or equal to the maxPitch provided. Comparisons between pitches are done using pitch diff --git a/music21/figuredBass/realizer.py b/music21/figuredBass/realizer.py index bbfd3b0358..b85ce92ddf 100644 --- a/music21/figuredBass/realizer.py +++ b/music21/figuredBass/realizer.py @@ -717,7 +717,7 @@ def generateRealizationFromPossibilityProgression(self, possibilityProgression): else: # Chorale-style output upperParts = [] - for partNumber in range(len(possibilityProgression[0]) - 1): + for _partNumber in range(len(possibilityProgression[0]) - 1): fbPart = stream.Part() sol.insert(0.0, fbPart) fbPart.append([copy.deepcopy(self._keySig), copy.deepcopy(self._inTime)]) diff --git a/music21/graph/findPlot.py b/music21/graph/findPlot.py index 63ec04d377..b57895251f 100644 --- a/music21/graph/findPlot.py +++ b/music21/graph/findPlot.py @@ -367,7 +367,7 @@ def _bestPlotType(graphClassesToChooseFrom): # no matches for values. Try agnostic about X and Y graphRemove = [] - for axisLetter, axisValue in (('x', xValue), ('y', yValue), ('z', zValue)): + for _axisLetter, axisValue in (('x', xValue), ('y', yValue), ('z', zValue)): for gc in graphClasses: if axisValue is None: continue diff --git a/music21/graph/primitives.py b/music21/graph/primitives.py index c69d2c87ec..815bd45466 100644 --- a/music21/graph/primitives.py +++ b/music21/graph/primitives.py @@ -1430,7 +1430,7 @@ def renderSubplot(self, subplot): rects = [] for i in range(barsPerGroup): yVals = [] - for j, x in enumerate(xVals): + for j, _x in enumerate(xVals): # get position, then get bar group yVals.append(yBundles[j][i]) xValsShifted = [] diff --git a/music21/metadata/__init__.py b/music21/metadata/__init__.py index 7e85b67666..c325113ee4 100755 --- a/music21/metadata/__init__.py +++ b/music21/metadata/__init__.py @@ -671,7 +671,7 @@ def copyright(self, value: str) -> None: ''' For type checking only. Does not run. ''' - setattr(self, 'copyright', value) + self.copyright = value # SPECIAL METHODS # def all( @@ -1302,7 +1302,7 @@ def alternativeTitle(self, value: str) -> None: ''' For type checking only. Does not run. ''' - setattr(self, 'alternativeTitle', value) + self.alternativeTitle = value @property def composer(self): @@ -1336,7 +1336,7 @@ def composer(self, value: str) -> None: ''' For type checking only. Does not run. ''' - setattr(self, 'composer', value) + self.composer = value @property def composers(self): @@ -1372,7 +1372,7 @@ def composers(self, value: Iterable[str]) -> None: ''' For type checking only. Does not run. ''' - setattr(self, 'composers', value) + self.composers = value @property def dateCreated(self): @@ -1405,7 +1405,7 @@ def dateCreated(self, value: str) -> None: ''' For type checking only. Does not run. ''' - setattr(self, 'dateCreated', value) + self.dateCreated = value @property def fileFormat(self) -> str|None: @@ -1419,7 +1419,7 @@ def fileFormat(self, value: str) -> None: ''' For type checking only. Does not run. ''' - setattr(self, 'fileFormat', value) + self.fileFormat = value @property def filePath(self) -> str|None: @@ -1434,7 +1434,7 @@ def filePath(self, value: str) -> None: ''' For type checking only. Does not run. ''' - setattr(self, 'filePath', value) + self.filePath = value @property def corpusFilePath(self) -> str|None: @@ -1448,7 +1448,7 @@ def corpusFilePath(self, value: str) -> None: ''' For type checking only. Does not run. ''' - setattr(self, 'corpusFilePath', value) + self.corpusFilePath = value @property def fileNumber(self) -> str|None: @@ -1462,7 +1462,7 @@ def fileNumber(self, value: str) -> None: ''' For type checking only. Does not run. ''' - setattr(self, 'fileNumber', value) + self.fileNumber = value @property def localeOfComposition(self): @@ -1481,7 +1481,7 @@ def localeOfComposition(self, value: str) -> None: ''' For type checking only. Does not run. ''' - setattr(self, 'localeOfComposition', value) + self.localeOfComposition = value @property def librettist(self): @@ -1504,7 +1504,7 @@ def librettist(self, value: str) -> None: ''' For type checking only. Does not run. ''' - setattr(self, 'librettist', value) + self.librettist = value @property def librettists(self): @@ -1525,7 +1525,7 @@ def librettists(self, value: Iterable[str]) -> None: ''' For type checking only. Does not run. ''' - setattr(self, 'librettists', value) + self.librettists = value @property def lyricist(self): @@ -1551,7 +1551,7 @@ def lyricist(self, value: str) -> None: ''' For type checking only. Does not run. ''' - setattr(self, 'lyricist', value) + self.lyricist = value @property def lyricists(self): @@ -1572,7 +1572,7 @@ def lyricists(self, value: Iterable[str]) -> None: ''' For type checking only. Does not run. ''' - setattr(self, 'lyricists', value) + self.lyricists = value @property def movementName(self): @@ -1595,7 +1595,7 @@ def movementName(self, value: str) -> None: ''' For type checking only. Does not run. ''' - setattr(self, 'movementName', value) + self.movementName = value @property def movementNumber(self) -> str|None: @@ -1618,7 +1618,7 @@ def movementNumber(self, value: str) -> None: ''' For type checking only. Does not run. ''' - setattr(self, 'movementNumber', value) + self.movementNumber = value @property def number(self) -> str|None: @@ -1648,7 +1648,7 @@ def number(self, value: str) -> None: ''' For type checking only. Does not run. ''' - setattr(self, 'number', value) + self.number = value @property def opusNumber(self) -> str|None: @@ -1678,7 +1678,7 @@ def opusNumber(self, value: str) -> None: ''' For type checking only. Does not run. ''' - setattr(self, 'opusNumber', value) + self.opusNumber = value @property def title(self): @@ -1700,7 +1700,7 @@ def title(self, value: str) -> None: ''' For type checking only. Does not run. ''' - setattr(self, 'title', value) + self.title = value @property def bestTitle(self) -> str|None: diff --git a/music21/metadata/caching.py b/music21/metadata/caching.py index 4e4b9f23bc..1f1e4d758f 100644 --- a/music21/metadata/caching.py +++ b/music21/metadata/caching.py @@ -347,7 +347,7 @@ def process_parallel(jobs, processCount=None): 'filePath': job.filePath, 'remainingJobs': remainingJobs, } - for worker in workers: + for _worker in workers: job_queue.put(None) job_queue.join() result_queue.close() diff --git a/music21/midi/translate.py b/music21/midi/translate.py index 00545a8bbf..9732098763 100644 --- a/music21/midi/translate.py +++ b/music21/midi/translate.py @@ -647,7 +647,7 @@ def midiEventsToChord( # this is a format provided by the Stream conversion of # midi events; it pre-groups events for a chord together in nested pairs # of abs start time and the event object - for tOn, tOff, eOn in timedNoteList: + for _tOn, _tOff, eOn in timedNoteList: if eOn.channel == 10: any_channel_10 = True p = pitch.Pitch() @@ -1676,7 +1676,7 @@ def assignPacketsToChannels( # after processing, collect all channels used foundChannels = [] - for start, stop, usedChannel in list(uniqueChannelEvents): # a list + for _start, _stop, usedChannel in list(uniqueChannelEvents): if usedChannel not in foundChannels: foundChannels.append(usedChannel) # for ch in chList: diff --git a/music21/musicxml/xmlToM21.py b/music21/musicxml/xmlToM21.py index 10a58b1154..298462ba00 100644 --- a/music21/musicxml/xmlToM21.py +++ b/music21/musicxml/xmlToM21.py @@ -6361,7 +6361,10 @@ def xmlStaffLayoutFromStaffDetails( stl.staffType = stream.enums.StaffType(xmlText) except ValueError: warnings.warn( - f'Got an incorrect staff-type in details: {mxStaffType}', MusicXMLWarning, stacklevel=2) + f'Got an incorrect staff-type in details: {mxStaffType}', + MusicXMLWarning, + stacklevel=2, + ) # TODO: staff-tuning* # TODO: capo seta(stl, mxDetails, 'staff-size', transform=_floatOrIntStr) diff --git a/music21/stream/base.py b/music21/stream/base.py index 2ddda531cd..6c7bbd2739 100644 --- a/music21/stream/base.py +++ b/music21/stream/base.py @@ -5814,7 +5814,12 @@ def getInstrument(self, ) return post.first() - def invertDiatonic(self, inversionNote: note.Note|None = None, *, inPlace=False): + def invertDiatonic( + self, + inversionNote: note.Note|None = None, + *, + inPlace: bool = False + ): ''' inverts a stream diatonically around the given note (by default, middle C) @@ -5881,23 +5886,23 @@ def invertDiatonic(self, inversionNote: note.Note|None = None, *, inPlace=False) keySigSearch = returnStream.recurse().getElementsByClass(key.KeySignature) - quickSearch = True + ourKey: key.KeySignature | None if not keySigSearch: ourKey = key.Key('C') elif len(keySigSearch) == 1: ourKey = keySigSearch[0] else: ourKey = None # for might be undefined warning - quickSearch = False inversionDNN = inversionNoteReal.pitch.diatonicNoteNum - for n in returnStream[note.NotRest]: + for n in returnStream[note.Note]: n.pitch.diatonicNoteNum = (2 * inversionDNN) - n.pitch.diatonicNoteNum - if quickSearch: # use previously found + if ourKey: # use previously found n.pitch.accidental = ourKey.accidentalByStep(n.pitch.step) else: # use context search ksActive = n.getContextByClass(key.KeySignature) - n.pitch.accidental = ksActive.accidentalByStep(n.pitch.step) + if ksActive: + n.pitch.accidental = ksActive.accidentalByStep(n.pitch.step) if n.pitch.accidental is not None: n.pitch.accidental.displayStatus = None diff --git a/pyproject.toml b/pyproject.toml index 4a5ab721e1..d5d6be4c18 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -93,6 +93,8 @@ ignore = [ 'E303', # do not assign lambda -- okay by me. 'E731', + # except and then raise without from -- should do soon. + 'B904', # zip without strict= ... nice to turn this off someday, when code more mature 'B905', ] From 4d7ec003310df72763e30b572817010296631dc1 Mon Sep 17 00:00:00 2001 From: Michael Scott Asato Cuthbert Date: Fri, 2 Jan 2026 17:42:05 -1000 Subject: [PATCH 09/13] format done --- music21/analysis/metrical.py | 2 +- music21/braille/segment.py | 28 +++++++++++++++++++--------- music21/corpus/manager.py | 7 ++++--- music21/figuredBass/checker.py | 6 +++--- music21/interval.py | 5 +++-- music21/layout.py | 11 ++++++----- music21/metadata/bundles.py | 7 ++++--- music21/roman.py | 14 +++++++++----- music21/search/base.py | 6 ++++-- music21/tree/core.py | 23 +++++++++++------------ music21/tree/node.py | 15 ++++++++------- music21/vexflow/toMusic21j.py | 4 ++-- 12 files changed, 74 insertions(+), 54 deletions(-) diff --git a/music21/analysis/metrical.py b/music21/analysis/metrical.py index e51023c682..10aa5222b9 100644 --- a/music21/analysis/metrical.py +++ b/music21/analysis/metrical.py @@ -43,7 +43,7 @@ def labelBeatDepth(streamIn): >>> sOut = [] >>> for n in s.flatten().notes: ... stars = "".join([l.text for l in n.lyrics]) - ... sOut.append("{0:8s} {1}".format(n.beatStr, stars)) + ... sOut.append(f'{n.beatStr:8s} {stars}') >>> print("\n".join(sOut)) 1 **** 1 1/2 * diff --git a/music21/braille/segment.py b/music21/braille/segment.py index adf7f0e056..c7e66ab1f5 100644 --- a/music21/braille/segment.py +++ b/music21/braille/segment.py @@ -429,14 +429,18 @@ def __str__(self): continue except TypeError: pass - allKeys.append('Measure {0}, {1} {2}:\n'.format(itemKey.measure, - affinityNames[itemKey.affinity], - itemKey.ordinal + 1)) + allKeys.append( + f'Measure {itemKey.measure}, ' + f'{affinityNames[itemKey.affinity]} ' + f'{itemKey.ordinal + 1}:\n' + ) gStr = str(grouping) allGroupings.append(gStr) prevKey = itemKey - allElementGroupings = '\n'.join([''.join([k, g, '\n===']) - for (k, g) in list(zip(allKeys, allGroupings))]) + allElementGroupings = '\n'.join( + f'{k}{g}\n===' + for k, g in zip(allKeys, allGroupings) + ) out = '\n'.join(['---begin segment---', name, allElementGroupings, @@ -1114,15 +1118,21 @@ def __str__(self): allPairs = [] for (rightKey, leftKey) in self.yieldCombinedGroupingKeys(): if rightKey is not None: - rightHeading = 'Measure {0} Right, {1} {2}:\n'.format( - rightKey.measure, affinityNames[rightKey.affinity], rightKey.ordinal + 1) + rightHeading = ( + f'Measure {rightKey.measure} Right, ' + f'{affinityNames[rightKey.affinity]} ' + f'{rightKey.ordinal + 1}:\n' + ) rightContents = str(self._groupingDict.get(rightKey)) rightFull = ''.join([rightHeading, rightContents]) else: rightFull = '' if leftKey is not None: - leftHeading = '\nMeasure {0} Left, {1} {2}:\n'.format( - leftKey.measure, affinityNames[leftKey.affinity], leftKey.ordinal + 1) + leftHeading = ( + f'\nMeasure {leftKey.measure} Left, ' + f'{affinityNames[leftKey.affinity]} ' + f'{leftKey.ordinal + 1}:\n' + ) leftContents = str(self._groupingDict.get(leftKey)) leftFull = ''.join([leftHeading, leftContents]) else: diff --git a/music21/corpus/manager.py b/music21/corpus/manager.py index 1114b9cf96..5f6c5ccb2f 100644 --- a/music21/corpus/manager.py +++ b/music21/corpus/manager.py @@ -355,9 +355,10 @@ def getMetadataBundleByCorpus(corpusObject: corpora.Corpus) -> bundles.MetadataB assert mdb is not None # cacheMetadataBundleFromDisk makes None impossible return mdb else: # pragma: no cover - raise CorpusException('No metadata bundle found for corpus {0} with name {1}'.format( - corpusObject, corpusName)) - + raise CorpusException( + f'No metadata bundle found for corpus {corpusObject} ' + f'with name {corpusName}' + ) def cacheMetadataBundleFromDisk(corpusObject: corpora.Corpus) -> None: r''' diff --git a/music21/figuredBass/checker.py b/music21/figuredBass/checker.py index 2c8bb80869..e39f20388c 100644 --- a/music21/figuredBass/checker.py +++ b/music21/figuredBass/checker.py @@ -85,7 +85,7 @@ def extractHarmonies(music21Stream): >>> from music21.figuredBass import checker >>> allHarmonies = checker.extractHarmonies(score) >>> for (offsets, notes) in sorted(allHarmonies.items()): - ... print('{0!s:15}[{1!s:23}{2!s:23}{3!s:22}]'.format(offsets, notes[0], notes[1], notes[2])) + ... print(f'{offsets!s:15}[{notes[0]!s:23}{notes[1]!s:23}{notes[2]!s:22}]') (0.0, 1.5) [ ] (1.5, 2.0) [ ] (2.0, 3.0) [ ] @@ -123,7 +123,7 @@ def createOffsetMapping(music21Part): >>> v0 = score[0] >>> offsetMapping = checker.createOffsetMapping(v0) >>> for (offsets, notes) in sorted(offsetMapping.items()): - ... print('{0!s:15}[{1!s:22}]'.format(offsets, notes[0])) + ... print(f'{offsets!s:15}[{notes[0]!s:22}]') (0.0, 1.5) [ ] (1.5, 2.0) [ ] (2.0, 3.0) [] @@ -157,7 +157,7 @@ def correlateHarmonies(currentMapping, music21Part): >>> v1 = score[1] >>> newMapping = checker.correlateHarmonies(offsetMapping, v1) >>> for (offsets, notes) in sorted(newMapping.items()): - ... print('{0!s:15}[{1!s:23}{2!s:21}]'.format(offsets, notes[0], notes[1])) + ... print(f'{offsets!s:15}[{notes[0]!s:23}{notes[1]!s:21}]') (0.0, 1.5) [ ] (1.5, 2.0) [ ] (2.0, 3.0) [ ] diff --git a/music21/interval.py b/music21/interval.py index 5951a3389b..c3b7798fa1 100644 --- a/music21/interval.py +++ b/music21/interval.py @@ -3962,8 +3962,9 @@ def transposePitch( else: if not hasattr(interval1, 'transposePitch'): raise IntervalException( - 'interval must be a music21.interval.Interval object not {}'.format( - interval1.__class__.__name__)) + 'interval must be a music21.interval.Interval object not ' + + interval1.__class__.__name__ + ) return interval1.transposePitch(pitch1, inPlace=inPlace) diff --git a/music21/layout.py b/music21/layout.py index 3f83def759..835dd5c2f3 100644 --- a/music21/layout.py +++ b/music21/layout.py @@ -1593,11 +1593,12 @@ def __init__(self, givenElements=None, **keywords): self.staffLayout = None def _reprInternal(self): - return '{0}: p.{1}, sys.{2}, st.{3}'.format(self.scoreStaffNumber, - self.pageNumber, - self.pageSystemNumber, - self.staffNumber) - + return ( + f'{self.scoreStaffNumber}: ' + + f'p.{self.pageNumber}, ' + + f'sys.{self.pageSystemNumber}, ' + + f'st.{self.staffNumber}' + ) _DOC_ORDER = [ScoreLayout, PageLayout, SystemLayout, StaffLayout, LayoutBase, LayoutScore, Page, System, Staff] diff --git a/music21/metadata/bundles.py b/music21/metadata/bundles.py index d04fabbd73..f0a6abd784 100644 --- a/music21/metadata/bundles.py +++ b/music21/metadata/bundles.py @@ -1116,9 +1116,10 @@ def read(self, filePath=None): filePath = pathlib.Path(filePath) if not filePath.exists(): - environLocal.printDebug('no metadata found for: {0!r}; ' - 'try building cache with corpus.cacheMetadata({1!r})'.format( - self.name, self.name)) + environLocal.printDebug( + f'no metadata found for: {self.name!r}; ' + + f'try building cache with corpus.cacheMetadata({self.name!r})' + ) return self newMdb = readPickleGzip(filePath) diff --git a/music21/roman.py b/music21/roman.py index 3bb53e3162..25bdf7eb2e 100644 --- a/music21/roman.py +++ b/music21/roman.py @@ -1234,10 +1234,12 @@ def romanNumeralFromChord( rn = RomanNumeral(rnString, keyObj, updatePitches=False, # correctRNAlterationForMinor() adds cautionary sixthMinor=Minor67Default.CAUTIONARY, seventhMinor=Minor67Default.CAUTIONARY) - except fbNotation.ModifierException as strerror: + except fbNotation.ModifierException as strerror: # pragma: no cover raise RomanNumeralException( - 'Could not parse {0} from chord {1} as an RN ' - 'in key {2}: {3}'.format(rnString, chordObj, keyObj, strerror)) # pragma: no cover + 'Could not parse ' + + f'{rnString} from chord {chordObj} as an RN ' + + f'in key {keyObj}: {strerror}' + ) from strerror # Is this linking them in an unsafe way? rn.pitches = chordObj.pitches @@ -3471,8 +3473,10 @@ def key(self, keyOrScale): keyClasses = keyOrScale.classes except AttributeError: # pragma: no cover raise RomanNumeralException( - 'Cannot call classes on object {0!r}, send only Key ' - 'or Scale Music21Objects'.format(keyOrScale)) + 'Cannot call classes on object ' + + f'{keyOrScale!r}, send only Key ' + + 'or Scale Music21Objects' + ) if 'Key' in keyClasses: # good to go if keyOrScale.tonicPitchNameWithCase not in _keyCache: diff --git a/music21/search/base.py b/music21/search/base.py index a8946e41ce..b11f91eddb 100644 --- a/music21/search/base.py +++ b/music21/search/base.py @@ -99,8 +99,10 @@ class SearchMatch(namedtuple('SearchMatch', ['elStart', 'els', 'index', 'iterato } def __repr__(self): - return 'SearchMatch(elStart={0}, els=len({1}), index={2}, iterator=[...])'.format( - repr(self.elStart), len(self.els), repr(self.index)) + es = self.elStart + el = len(self.els) + ix = self.index + return f'SearchMatch(elStart={es!r}, els=len({el}), index={ix!r}, iterator=[...])' class StreamSearcher: diff --git a/music21/tree/core.py b/music21/tree/core.py index 408c0e3e9f..940ff3bf4f 100644 --- a/music21/tree/core.py +++ b/music21/tree/core.py @@ -242,20 +242,19 @@ def __init__(self, position, payload=None): # SPECIAL METHODS # def __repr__(self): - lcHeight = None + lch = None if self.leftChild: - lcHeight = self.leftChild.height - rcHeight = None + lch = self.leftChild.height + + rch = None if self.rightChild: - rcHeight = self.rightChild.height - - return '<{}: Start:{} Height:{} L:{} R:{}>'.format( - self.__class__.__name__, - self.position, - self.height, - lcHeight, - rcHeight - ) + rch = self.rightChild.height + + cn = self.__class__.__name__ + ps = self.position + ht = self.height + + return f'<{cn}: Start:{ps} Height:{ht} L:{lch} R:{rch}>' def moveAttributes(self, other): ''' diff --git a/music21/tree/node.py b/music21/tree/node.py index c9f2d29480..9b4aaba398 100644 --- a/music21/tree/node.py +++ b/music21/tree/node.py @@ -181,13 +181,14 @@ def __repr__(self): pos = self.position if hasattr(pos, 'shortRepr'): pos = pos.shortRepr() - return ''.format( - pos, - self.subtreeElementsStartIndex, - self.payloadElementIndex, - self.subtreeElementsStopIndex, - self.payload, - ) + + ps = pos + li = self.subtreeElementsStartIndex + pi = self.payloadElementIndex + ri = self.subtreeElementsStopIndex + pl = self.payload + + return f'' # PROPERTIES # @property diff --git a/music21/vexflow/toMusic21j.py b/music21/vexflow/toMusic21j.py index 62ad8775bc..f02da97dd1 100644 --- a/music21/vexflow/toMusic21j.py +++ b/music21/vexflow/toMusic21j.py @@ -241,8 +241,8 @@ def getHTML(self, dataSplit, title=None, defaults=None): loadM21Formatted = self.getLoadTemplate(d) jsBodyScript = self.getJSBodyScript(dataSplit, d) formatted = self.templateHtml.format(title=title, - loadM21Template=loadM21Formatted, - jsBodyScript=jsBodyScript) + loadM21Template=loadM21Formatted, + jsBodyScript=jsBodyScript) return formatted def fromStream(self, thisStream, mode=None): From a28f768b71f77e04c3ee9ede23495119149cff46 Mon Sep 17 00:00:00 2001 From: Michael Scott Asato Cuthbert Date: Fri, 2 Jan 2026 21:31:30 -1000 Subject: [PATCH 10/13] fix some problems --- .pylintrc | 2 +- music21/corpus/__init__.py | 4 ++-- music21/figuredBass/possibility.py | 2 ++ music21/layout.py | 1 + music21/midi/tests.py | 7 +++++-- music21/stream/base.py | 2 +- 6 files changed, 12 insertions(+), 6 deletions(-) diff --git a/.pylintrc b/.pylintrc index b901d91df8..fb797479d0 100644 --- a/.pylintrc +++ b/.pylintrc @@ -290,7 +290,7 @@ init-import=no # A regular expression matching the name of dummy variables (i.e. expectedly # not used). -dummy-variables-rgx=_$|dummy|unused|i$|j$|junk|counter +dummy-variables-rgx=_|dummy|unused|i$|j$|junk|counter # List of additional names supposed to be defined in builtins. Remember that # you should avoid to define new builtins when possible. diff --git a/music21/corpus/__init__.py b/music21/corpus/__init__.py index 12704fb6ac..38cacecc0e 100644 --- a/music21/corpus/__init__.py +++ b/music21/corpus/__init__.py @@ -47,7 +47,7 @@ from music21.corpus import chorales from music21.corpus import corpora from music21.corpus import manager -# from music21.corpus import virtual +from music21.corpus import virtual from music21.corpus import work from music21.corpus.manager import search from music21 import environment @@ -67,7 +67,7 @@ 'manager', 'noCorpus', 'parse', - # virtual + 'virtual', 'search', 'work', ] diff --git a/music21/figuredBass/possibility.py b/music21/figuredBass/possibility.py index 3f8c30d9c6..f3944f5a99 100644 --- a/music21/figuredBass/possibility.py +++ b/music21/figuredBass/possibility.py @@ -198,8 +198,10 @@ def upperPartsWithinLimit(possibA, maxSemitoneSeparation=12): return areUpperPartsWithinLimit + DEFAULT_MAX_PITCH = pitch.Pitch('B5') + def pitchesWithinLimit(possibA, maxPitch=DEFAULT_MAX_PITCH): ''' Returns True if all pitches in possibA are less than or equal to diff --git a/music21/layout.py b/music21/layout.py index 835dd5c2f3..b16fa4e797 100644 --- a/music21/layout.py +++ b/music21/layout.py @@ -1600,6 +1600,7 @@ def _reprInternal(self): + f'st.{self.staffNumber}' ) + _DOC_ORDER = [ScoreLayout, PageLayout, SystemLayout, StaffLayout, LayoutBase, LayoutScore, Page, System, Staff] # ------------------------------------------------------------------------------ diff --git a/music21/midi/tests.py b/music21/midi/tests.py index 95363e9f99..7ccd1cd2fd 100644 --- a/music21/midi/tests.py +++ b/music21/midi/tests.py @@ -1273,10 +1273,13 @@ def testImportChordVoiceA(self): # looking at cases where notes appear to be chord but # are better seen as voices # specialized problem of not importing last notes + + # voice 1 -- m1 (half E G) m2 (F# B) m3 -- Chord C4C5 (zero duration?) + # voice 2 -- m1 whole C m2 whole D -- m3 (not existent) dirLib = common.getSourceFilePath() / 'midi' / 'testPrimitive' fp = dirLib / 'test13.mid' s = converter.parse(fp) - # s.show('t') + # s.show('text', addEndTimes=True) self.assertEqual(len(s.flatten().notes), 7) # s.show('midi') @@ -1291,7 +1294,7 @@ def testImportChordsA(self): fp = dirLib / 'test05.mid' # a simple file created in athenacl - s = converter.parse(fp) + s = converter.parse(fp, forceSource=True) # s.show('t') self.assertEqual(len(s[chord.Chord]), 5) diff --git a/music21/stream/base.py b/music21/stream/base.py index 6c7bbd2739..5f4f5936cd 100644 --- a/music21/stream/base.py +++ b/music21/stream/base.py @@ -8580,7 +8580,7 @@ def _getSeconds(self): mm = ti.getSoundingMetronomeMark() offsetMetronomeMarkPairs.append([o, mm]) - if len(offsetMetronomeMarkPairs) and offsetMetronomeMarkPairs[0][0] > 0.0: + if offsetMetronomeMarkPairs and offsetMetronomeMarkPairs[0][0] > 0.0: getTempoFromContext = True if getTempoFromContext: From 417b01dce93b5d1ac9b446f4beafed7c56f44257 Mon Sep 17 00:00:00 2001 From: Michael Scott Asato Cuthbert Date: Fri, 2 Jan 2026 22:14:03 -1000 Subject: [PATCH 11/13] fix midiEventsToChord! Wow was that not working the way it was supposed to! --- music21/midi/tests.py | 4 ++-- music21/midi/translate.py | 43 ++++++++++++++++++--------------------- 2 files changed, 22 insertions(+), 25 deletions(-) diff --git a/music21/midi/tests.py b/music21/midi/tests.py index 7ccd1cd2fd..8ddbdd38ad 100644 --- a/music21/midi/tests.py +++ b/music21/midi/tests.py @@ -1294,8 +1294,8 @@ def testImportChordsA(self): fp = dirLib / 'test05.mid' # a simple file created in athenacl - s = converter.parse(fp, forceSource=True) - # s.show('t') + s = converter.parse(fp) + # s.show('text') self.assertEqual(len(s[chord.Chord]), 5) def testMidiEventsImported(self): diff --git a/music21/midi/translate.py b/music21/midi/translate.py index 9732098763..6e6a13965b 100644 --- a/music21/midi/translate.py +++ b/music21/midi/translate.py @@ -318,7 +318,6 @@ def music21ObjectToMidiFile( # Notes def _constructOrUpdateNotRestSubclass( - eOn: MidiEvent, tOn: int, tOff: int, ticksPerQuarter: int, @@ -329,11 +328,9 @@ def _constructOrUpdateNotRestSubclass( Construct (or edit the duration of) a NotRest subclass, usually a note.Note (or a chord.Chord if provided to `returnClass`). - If the MidiEvent is on channel 10, then an Unpitched or PercussionChord - is constructed instead. Raises TypeError if an incompatible class is provided - for returnClass. - * Changed in v8: no inputM21 + * Changed in v10: Remove part about creating an Unpitched object -- that has been wrong + for some time (probably since PercussionChords were introduced) ''' if not issubclass(returnClass, note.NotRest): raise TypeError(f'Expected subclass of note.NotRest; got {returnClass}') @@ -421,16 +418,15 @@ def midiEventsToNote( The only supported usage now is two tuples. * Changed in v9.7: Expects a single TimedNoteEvent ''' - tOn, tOff, eOn = timedNoteEvent + tOn, tOff, midiOnEvent = timedNoteEvent returnClass: type[note.Unpitched]|type[note.Note] - if eOn.channel == 10: + if midiOnEvent.channel == 10: returnClass = note.Unpitched else: returnClass = note.Note nr = _constructOrUpdateNotRestSubclass( - eOn, tOn, tOff, ticksPerQuarter, @@ -438,10 +434,10 @@ def midiEventsToNote( ) if isinstance(nr, note.Note): - nr.pitch.midi = eOn.pitch + nr.pitch.midi = midiOnEvent.pitch elif isinstance(nr, note.Unpitched): try: - i = PERCUSSION_MAPPER.midiPitchToInstrument(eOn.pitch) + i = PERCUSSION_MAPPER.midiPitchToInstrument(midiOnEvent.pitch) except MIDIPercussionException: i = instrument.UnpitchedPercussion() nr.storedInstrument = i @@ -451,9 +447,8 @@ def midiEventsToNote( f'Got something other than a Note or Unpitched from conversion: {nr}' ) - nr.volume.velocity = eOn.velocity + nr.volume.velocity = midiOnEvent.velocity nr.volume.velocityIsRelative = False # not relative coming from MIDI - # n._midiVelocity = eOn.velocity return t.cast(note.Note|note.Unpitched, nr) @@ -636,24 +631,27 @@ def midiEventsToChord( * Changed in v8: inputM21 is no longer supported. Flat list format is removed. * Changed in v9.7: expects a list of TimedNoteEvents ''' - tOn: int = 0 # ticks - tOff: int = 0 # ticks + # * Changed in v10: Fix long-standing bug where only the first on-time was being used + # not yet -- must fix quantization tests to do so... + # THIS IS A BUG -- should be timedNoteList[0] + # fixing it breaks stream/tests/testQuantizeMinimumDuration though, so a separate PR + first_tOn: int = timedNoteList[-1][0] # ticks + last_tOff: int = timedNoteList[-1][1] # ticks pitches: list[pitch.Pitch] = [] - volumes = [] + volumes: list[volume.Volume] = [] - firstOn: MidiEvent = timedNoteList[0].event any_channel_10 = False # this is a format provided by the Stream conversion of # midi events; it pre-groups events for a chord together in nested pairs # of abs start time and the event object - for _tOn, _tOff, eOn in timedNoteList: - if eOn.channel == 10: + for _tOn, _tOff, midiOnEvent in timedNoteList: + if midiOnEvent.channel == 10: any_channel_10 = True p = pitch.Pitch() - p.midi = eOn.pitch + p.midi = midiOnEvent.pitch pitches.append(p) - v = volume.Volume(velocity=eOn.velocity) + v = volume.Volume(velocity=midiOnEvent.velocity) v.velocityIsRelative = False # velocity is absolute coming from MIDI volumes.append(v) @@ -664,9 +662,8 @@ def midiEventsToChord( returnClass = chord.Chord c = _constructOrUpdateNotRestSubclass( - firstOn, - tOn, - tOff, + first_tOn, + last_tOff, ticksPerQuarter, returnClass=returnClass ) From 3a881af7be2c53ade7197b961dc3696353d3b318 Mon Sep 17 00:00:00 2001 From: Michael Scott Asato Cuthbert Date: Fri, 2 Jan 2026 22:49:08 -1000 Subject: [PATCH 12/13] lint and fraction --- .../developerGuidelines.ipynb | 13 ++++++---- music21/abcFormat/__init__.py | 4 ++-- music21/analysis/correlate.py | 2 +- music21/analysis/reduction.py | 2 +- music21/audioSearch/__init__.py | 2 +- music21/base.py | 14 +++++------ music21/braille/basic.py | 4 ++-- music21/braille/segment.py | 24 ++++++++++--------- music21/clef.py | 2 +- music21/corpus/chorales.py | 6 ++--- music21/duration.py | 5 ++-- music21/expressions.py | 4 ++-- music21/features/base.py | 10 ++++---- music21/figuredBass/realizer.py | 3 ++- music21/humdrum/spineParser.py | 6 ++--- music21/layout.py | 8 +++---- music21/lily/lilyObjects.py | 9 +++---- music21/lily/translate.py | 2 +- music21/metadata/bundles.py | 2 +- music21/metadata/caching.py | 8 +++---- music21/meter/base.py | 2 +- music21/meter/core.py | 12 +++++----- music21/meter/tools.py | 8 +++---- music21/musicxml/m21ToXml.py | 4 ++-- music21/musicxml/xmlToM21.py | 4 ++-- music21/note.py | 2 +- music21/pitch.py | 2 +- music21/repeat.py | 4 ++-- music21/roman.py | 8 +++---- music21/romanText/rtObjects.py | 4 ++-- music21/romanText/translate.py | 8 +++---- music21/search/base.py | 2 +- music21/search/lyrics.py | 9 +++---- music21/sites.py | 4 ++-- music21/spanner.py | 6 ++--- music21/stream/base.py | 10 ++++---- music21/stream/core.py | 2 +- music21/stream/makeNotation.py | 8 +++---- music21/tablature.py | 4 ++-- music21/tempo.py | 9 ++++--- music21/test/multiprocessTest.py | 22 ++++++++--------- music21/test/testRunner.py | 3 +-- music21/tinyNotation.py | 6 ++--- music21/tree/timespanTree.py | 3 +-- music21/tree/toStream.py | 6 +++-- music21/voiceLeading.py | 2 +- 46 files changed, 149 insertions(+), 135 deletions(-) diff --git a/documentation/source/developerReference/developerGuidelines.ipynb b/documentation/source/developerReference/developerGuidelines.ipynb index 07fb94f9e9..333245507c 100644 --- a/documentation/source/developerReference/developerGuidelines.ipynb +++ b/documentation/source/developerReference/developerGuidelines.ipynb @@ -145,14 +145,17 @@ "Conventions:\n", "\n", " - **Strings MUST be 'single-quoted', but \"double quotes\" are allowed internally**\n", - " - This rule applies to triple quotes and doc strings also, contrary to PEP 257.\n", - " - Docstrings must begin and end on their own lines. No one-line doc-strings or text\n", + " - This rule applies to triple quotes and docstrings also, contrary to PEP 257.\n", + " - Docstrings must begin and end on their own lines. No one-line docstrings or text\n", " immediately following the triple quotes.\n", " - When there is a hyphen or single quote in the string, double quotes should be used,\n", " not escaping/backslashing.\n", " - For long streams of TinyNotation or Lilypond code, which both use single quotes to indicate octave,\n", " triple single quotes around the string are better than double quotes. Internal whitespace\n", " rarely matters in those formats.\n", + " - Before v10 concatenating strings without a plus sign was discouraged. I've changed my mind,\n", + " and am \"letting Python be Python\" now especially when three or more lines are involved.\n", + " However, use a + sign if concatenation is mixed with different comma-separated arguments.\n", " - Documentation should follow quoting in American English grammar when not\n", " discussing code. So for instance, a quotation in documentation is in double quotes.\n", " - Variable names:\n", @@ -163,7 +166,8 @@ " - Line lengths are capped at 100, but if approaching this limit, look for ways to avoid one-lining.\n", " - if it's easy to split your line into two which are both under 80 characters, do so.\n", " - Line continuation characters (`\\`) are not allowed; use open parentheses.\n", - " - Prefer f-strings to `.format()`. The `%` interpolation is no longer allowed.\n", + " - Greatly prefer f-strings to `.format()`. The `%` interpolation is no longer allowed.\n", + " - `.format()` is only to be used when a repeated format string is involved.\n", " - Annotating types is **required** in new code, and encouraged to be added to older code.\n", " - e.g. `self.counter: int = 0` or `def makeNoises() -> list['noise.Noise']:`\n", " - The typing library should always be imported as `t`.\n", @@ -193,7 +197,8 @@ " manipulation of the original object. When `inPlace` is True, nothing should be returned\n", " (not true for `music21j` since passing through objects is so expected in JavaScript thanks\n", " to JQuery and other libraries). Use the `@overload` decorator to show how this parameter\n", - " affects the return value -- Python makes this a bit hard, but see for instance, :meth:`~music21.stream.base.Stream.getElementsByClass` for an example of how to use this.\n", + " affects the return value -- Python makes this a bit hard, but see for\n", + " instance, :meth:`~music21.stream.base.Stream.getElementsByClass` for an example of how to use this.\n", " - Use descriptive pull request titles (rather than GitHub's default \"Update pitch.py\")\n", " - Do not have a PR title so long that it cannot be seen in one line. Simplify and\n", " rewrite and go into more detail in the description. I depend on skimming PR titles\n", diff --git a/music21/abcFormat/__init__.py b/music21/abcFormat/__init__.py index bf279c8fde..5772d98d2d 100644 --- a/music21/abcFormat/__init__.py +++ b/music21/abcFormat/__init__.py @@ -2621,7 +2621,7 @@ def tokenProcess(self) -> None: else: environLocal.printDebug( ['broken rhythm marker ' - + f'({token.src}) not positioned between two notes or chords']) + f'({token.src}) not positioned between two notes or chords']) # need to update tuplets with currently active meter if isinstance(token, ABCTuplet): @@ -2698,7 +2698,7 @@ def tokenProcess(self) -> None: if lastDefaultQL is None: raise ABCHandlerException( 'no active default note length provided for note processing. ' - + f'tPrev: {tPrev}, token: {token}, tNext: {tNext}' + f'tPrev: {tPrev}, token: {token}, tNext: {tNext}' ) token.activeDefaultQuarterLength = lastDefaultQL token.activeKeySignature = lastKeySignature diff --git a/music21/analysis/correlate.py b/music21/analysis/correlate.py index f43702b2f2..563d94c393 100644 --- a/music21/analysis/correlate.py +++ b/music21/analysis/correlate.py @@ -131,7 +131,7 @@ def pitchToDynamic(self, dataPoints=True): dstCheck = self.streamObj.recurse().getElementsByClass(objName) if not dstCheck: raise CorrelateException('cannot create correlation: an object ' - + f'that is not found in the Stream: {objName}') + f'that is not found in the Stream: {objName}') self._findActive(objNameSrc, objNameDst) diff --git a/music21/analysis/reduction.py b/music21/analysis/reduction.py index 58807b9f04..e850be322d 100644 --- a/music21/analysis/reduction.py +++ b/music21/analysis/reduction.py @@ -1095,7 +1095,7 @@ def _matchWeightedData(self, match, target): dataMatch[2], dataTarget[2], msg=(f'for partId {partId}, entry {i}: ' - + f'should be {dataMatch[2]} <-> was {dataTarget[2]}') + f'should be {dataMatch[2]} <-> was {dataTarget[2]}') ) def testPartReductionB(self, show=False): diff --git a/music21/audioSearch/__init__.py b/music21/audioSearch/__init__.py index 9fb7347c43..92a99681ca 100644 --- a/music21/audioSearch/__init__.py +++ b/music21/audioSearch/__init__.py @@ -140,7 +140,7 @@ def autocorrelationFunction(recordedSignal, recordSampleRateIn): # len(_missingImport) > 0: raise AudioSearchException( 'Cannot run autocorrelationFunction without ' - + f'numpy installed (scipy recommended). Missing {bmi}') + f'numpy installed (scipy recommended). Missing {bmi}') import numpy convolve = None try: diff --git a/music21/base.py b/music21/base.py index 6bcdae4809..775baaf721 100644 --- a/music21/base.py +++ b/music21/base.py @@ -245,7 +245,7 @@ class Groups(list): # no need to inherit from slotted object def _validName(self, value: str) -> None: if not isinstance(value, str): raise exceptions21.GroupException('Only strings can be used as group names, ' - + f'not {value!r}') + f'not {value!r}') # if ' ' in value: # raise exceptions21.GroupException('Spaces are not allowed as group names') @@ -2110,7 +2110,7 @@ def contextSites( memo.add(siteObj) environLocal.printDebug( f'looking in contextSites for {siteObj}' - + f' with position {positionInStream.shortRepr()}') + f' with position {positionInStream.shortRepr()}') for topLevel, inStreamPos, recurType in siteObj.contextSites( callerFirst=callerFirst, memo=memo, @@ -2144,7 +2144,7 @@ def contextSites( for derivedObject in topLevel.derivation.chain(): environLocal.printDebug( 'looking now in derivedObject, ' - + f'{derivedObject} with offsetAppend {offsetAppend}') + f'{derivedObject} with offsetAppend {offsetAppend}') for derivedCsTuple in derivedObject.contextSites( callerFirst=None, memo=memo, @@ -2441,7 +2441,7 @@ def _setActiveSite(self, site: stream.Stream|None): except SitesException as se: raise SitesException( 'activeSite cannot be set for ' - + f'object {self} not in the Stream {site}' + f'object {self} not in the Stream {site}' ) from se self._activeSiteStoredOffset = storedOffset @@ -3219,7 +3219,7 @@ def splitAtQuarterLength( if quarterLength > self.duration.quarterLength: raise DurationException( f'cannot split a duration ({self.duration.quarterLength}) ' - + f'at this quarterLength ({quarterLength})' + f'at this quarterLength ({quarterLength})' ) if retainOrigin is True: @@ -3379,8 +3379,8 @@ def splitByQuarterLengths( if opFrac(sum(quarterLengthList)) != self.duration.quarterLength: raise Music21ObjectException( 'cannot split by quarter length list whose sum is not ' - + 'equal to the quarterLength duration of the source: ' - + f'{quarterLengthList}, {self.duration.quarterLength}' + 'equal to the quarterLength duration of the source: ' + f'{quarterLengthList}, {self.duration.quarterLength}' ) # if nothing to do diff --git a/music21/braille/basic.py b/music21/braille/basic.py index aae0121d71..63ef592452 100644 --- a/music21/braille/basic.py +++ b/music21/braille/basic.py @@ -204,7 +204,7 @@ def chordToBraille(music21Chord, descending=True, showOctave=True): except KeyError: environRules.warn( f'Accidental {currentPitch.accidental} of ' - + f'chord {music21Chord} cannot be transcribed to braille.' + f'chord {music21Chord} cannot be transcribed to braille.' ) intervalDistance = interval.notesToGeneric(basePitch, currentPitch).undirected if intervalDistance > 8: @@ -1115,7 +1115,7 @@ def timeSigToBraille(m21TimeSignature): brailleSig = ''.join(timeSigTrans) m21TimeSignature.editorial.brailleEnglish.append( f'Time Signature {m21TimeSignature.numerator}/{m21TimeSignature.denominator} ' - + f'{brailleSig}' + f'{brailleSig}' ) return brailleSig except (BrailleBasicException, KeyError) as unused_error: # pragma: no cover diff --git a/music21/braille/segment.py b/music21/braille/segment.py index c7e66ab1f5..951e5af476 100644 --- a/music21/braille/segment.py +++ b/music21/braille/segment.py @@ -442,9 +442,9 @@ def __str__(self): for k, g in zip(allKeys, allGroupings) ) out = '\n'.join(['---begin segment---', - name, - allElementGroupings, - '---end segment---']) + name, + allElementGroupings, + '---end segment---']) return out def transcribe(self): @@ -1138,8 +1138,10 @@ def __str__(self): else: leftFull = '' allPairs.append('\n'.join([rightFull, leftFull, '====\n'])) - out = '\n'.join(['---begin grand segment---', name, ''.join(allPairs), - '---end grand segment---']) + out = '\n'.join(['---begin grand segment---', + name, + ''.join(allPairs), + '---end grand segment---']) return out def yieldCombinedGroupingKeys(self): @@ -1253,10 +1255,10 @@ def matchOther(thisKey_inner, otherKey): # except ValueError as ve: # raise BrailleSegmentException( # 'Misaligned braille groupings: ' - # + f'groupingKeyLeft was {gkLeft} ' - # + f'groupingKeyRight was {gkRight} ' - # + f'rightSegment was {rightSegment}, ' - # + f'leftSegment was {leftSegment}' + # f'groupingKeyLeft was {gkLeft} ' + # f'groupingKeyRight was {gkRight} ' + # f'rightSegment was {rightSegment}, ' + # f'leftSegment was {leftSegment}' # ) from ve # # try: @@ -2369,7 +2371,7 @@ def splitMeasure(music21Measure, beatDivisionOffset=0, useTimeSignature=None): if abs(beatDivisionOffset) > len(ts.beatDivisionDurations): raise BrailleSegmentException( f'beatDivisionOffset {beatDivisionOffset} is outside ' - + f'of ts.beatDivisionDurations {ts.beatDivisionDurations}' + f'of ts.beatDivisionDurations {ts.beatDivisionDurations}' ) duration_index = len(ts.beatDivisionDurations) - abs(beatDivisionOffset) try: @@ -2377,7 +2379,7 @@ def splitMeasure(music21Measure, beatDivisionOffset=0, useTimeSignature=None): offset = opFrac(offset) except IndexError: environRules.warn('Problem in converting a time signature in measure ' - + f'{music21Measure.number}, offset may be wrong') + f'{music21Measure.number}, offset may be wrong') bs = copy.deepcopy(ts.beatSequence) numberOfPartitions = 2 diff --git a/music21/clef.py b/music21/clef.py index 2bbe5c9626..b81f6ec812 100644 --- a/music21/clef.py +++ b/music21/clef.py @@ -858,7 +858,7 @@ def clefFromString(clefString, octaveShift=0) -> Clef: if lineNum < 1 or lineNum > 5: raise ClefException('line number (second character) must be 1-5; do not use this ' - + f'function for clefs on special staves such as {xnStr!r}') + f'function for clefs on special staves such as {xnStr!r}') clefObj: Clef if thisType in CLASS_FROM_TYPE: diff --git a/music21/corpus/chorales.py b/music21/corpus/chorales.py index e6a2386813..9987ddf1ac 100644 --- a/music21/corpus/chorales.py +++ b/music21/corpus/chorales.py @@ -1273,7 +1273,7 @@ def _returnChorale(self, choraleIndex=None): try: nextIndex = self._currentIndex + 1 riemenschneiderName = ('bach/choraleAnalyses/' - + f'riemenschneider{nextIndex:03d}.rntxt') + f'riemenschneider{nextIndex:03d}.rntxt') analysis = corpus.parse(riemenschneiderName) if analysis is not None: chorale.insert(0, analysis.parts[0]) @@ -1582,7 +1582,7 @@ def currentNumber(self, value): else: raise BachException( f'{value} does not correspond to a chorale in the ' - + f'{self.numberingSystem} numbering system' + f'{self.numberingSystem} numbering system' ) elif self._iterationType == 'index': @@ -1699,7 +1699,7 @@ def highestNumber(self, value): else: raise BachException( f'{value} does not correspond to a chorale in the ' - + f'{self.numberingSystem} numbering system' + f'{self.numberingSystem} numbering system' ) # - Return Type diff --git a/music21/duration.py b/music21/duration.py index 0b5dcc6f04..2a9e739fb5 100644 --- a/music21/duration.py +++ b/music21/duration.py @@ -250,7 +250,7 @@ def quarterLengthToClosestType(qLen: OffsetQLIn) -> tuple[str, bool]: ''' def raise_it(qLen_inner): return DurationException('Cannot return types smaller than 2048th; ' - + f'qLen was: {qLen}') + f'qLen was: {qLen}') if not qLen: raise raise_it(qLen) @@ -2122,7 +2122,8 @@ def componentStartTime(self, componentIndex: int) -> float: if not (0 <= componentIndex < len(self.components)): raise IndexError( f'invalid component index value {componentIndex} ' - + f'submitted; value must be an integer between 0 and {len(self.components) - 1}') + f'submitted; value must be an integer between 0 and {len(self.components) - 1}' + ) components = self.components[:componentIndex] return float(sum([c.quarterLength for c in components])) diff --git a/music21/expressions.py b/music21/expressions.py index 08da2e730c..8596c3f6ad 100644 --- a/music21/expressions.py +++ b/music21/expressions.py @@ -2835,7 +2835,7 @@ def __init__(self, arpeggioType: str|None = None, **keywords): if arpeggioType not in ('normal', 'up', 'down', 'non-arpeggio'): raise ValueError( 'Arpeggio type must be "normal", "up", "down", or "non-arpeggio", ' - + f'not {arpeggioType!r}.' + f'not {arpeggioType!r}.' ) self.type = arpeggioType @@ -2874,7 +2874,7 @@ def __init__(self, if arpeggioType not in ('normal', 'up', 'down', 'non-arpeggio'): raise ValueError( 'Arpeggio type must be "normal", "up", "down", or "non-arpeggio", ' - + f'not {arpeggioType!r}.' + f'not {arpeggioType!r}.' ) self.type = arpeggioType diff --git a/music21/features/base.py b/music21/features/base.py index 2cbc216a73..41a606540a 100644 --- a/music21/features/base.py +++ b/music21/features/base.py @@ -1083,7 +1083,7 @@ def write(self, fp=None, format=None, includeClassLabel=True): outputFormat = self._getOutputFormat(format) if outputFormat is None: raise DataSetException('no output format could be defined from file path ' - + f'{fp} or format {format}') + f'{fp} or format {format}') return outputFormat.write(fp=fp, includeClassLabel=includeClassLabel) @@ -1694,8 +1694,8 @@ def x_testRegionClassificationJSymbolicB(self): # pragma: no cover # # print( # f'{classifierStr} {classifierType}: misclassified ' - # + f'{mismatch}/{len(matchData)} of ' - # + f'{matchStr}' + # f'{mismatch}/{len(matchData)} of ' + # f'{matchStr}' # ) # # # if classifierType == orngTree.TreeLearner: @@ -1746,8 +1746,8 @@ def x_testRegionClassificationJSymbolicB(self): # pragma: no cover # # print( # f'{classifierStr} {classifierType}: misclassified ' - # + f'{mismatch}/{len(matchData)} of ' - # + f'{matchStr}' + # f'{mismatch}/{len(matchData)} of ' + # f'{matchStr}' # ) # def xtestOrangeClassifiers(self): # pragma: no cover diff --git a/music21/figuredBass/realizer.py b/music21/figuredBass/realizer.py index b85ce92ddf..2ad803df3e 100644 --- a/music21/figuredBass/realizer.py +++ b/music21/figuredBass/realizer.py @@ -273,7 +273,8 @@ def addElement(self, bassObject: note.Note, notationString=None): else: raise FiguredBassLineException( 'Not a valid bassObject (only note.Note, ' - + f'harmony.ChordSymbol, and roman.RomanNumeral supported) was {bassObject!r}') + f'harmony.ChordSymbol, and roman.RomanNumeral supported) was {bassObject!r}' + ) def generateBassLine(self): ''' diff --git a/music21/humdrum/spineParser.py b/music21/humdrum/spineParser.py index a8beac4e13..782105ee37 100644 --- a/music21/humdrum/spineParser.py +++ b/music21/humdrum/spineParser.py @@ -677,7 +677,7 @@ def createHumdrumSpines(self, protoSpines=None, eventCollections=None): if exchangeActive is not False: raise HumdrumException('ProtoSpine found with unpaired exchange instruction ' - + f'at line {i} [{thisEventCollection.events}]') + f'at line {i} [{thisEventCollection.events}]') currentSpineList = newSpineList return spineCollection @@ -920,10 +920,10 @@ def __init__(self, position: int = 0, contents: str = '!!! NUL: None'): value = value.strip() if code is None: raise HumdrumException('GlobalReferenceLine (!!!) found without a code ' - + f'listed; this is probably a problem! {contents} ') + f'listed; this is probably a problem! {contents} ') except IndexError: # pragma: no cover raise HumdrumException('GlobalReferenceLine (!!!) found without a code listed; ' - + f'this is probably a problem! {contents} ') + f'this is probably a problem! {contents} ') self.contents = contents self.code = code diff --git a/music21/layout.py b/music21/layout.py index b16fa4e797..85ad5dfac0 100644 --- a/music21/layout.py +++ b/music21/layout.py @@ -381,7 +381,7 @@ def __init__(self, def _reprInternal(self): return (f'distance {self.distance!r}, staffNumber {self.staffNumber!r}, ' - + f'staffSize {self.staffSize!r}, staffLines {self.staffLines!r}') + f'staffSize {self.staffSize!r}, staffLines {self.staffLines!r}') # ------------------------------------------------------------------------------ @@ -1595,9 +1595,9 @@ def __init__(self, givenElements=None, **keywords): def _reprInternal(self): return ( f'{self.scoreStaffNumber}: ' - + f'p.{self.pageNumber}, ' - + f'sys.{self.pageSystemNumber}, ' - + f'st.{self.staffNumber}' + f'p.{self.pageNumber}, ' + f'sys.{self.pageSystemNumber}, ' + f'st.{self.staffNumber}' ) diff --git a/music21/lily/lilyObjects.py b/music21/lily/lilyObjects.py index e9281d9231..0be88e3e74 100644 --- a/music21/lily/lilyObjects.py +++ b/music21/lily/lilyObjects.py @@ -143,10 +143,10 @@ def setAttributes(self, m21Object): foundClass = True break - if foundClass is False: # pragma: no cover + if not foundClass: # pragma: no cover raise LilyObjectsException( 'Could not support setting attributes from ' - + f'{m21Object}: supported classes: {self.supportedClasses}') + f'{m21Object}: supported classes: {self.supportedClasses}') return attrs def setAttributesFromClassObject(self, classLookup, m21Object): @@ -188,8 +188,9 @@ def setAttributesFromClassObject(self, classLookup, m21Object): if classLookup not in self.m21toLy: # pragma: no cover raise LilyObjectsException( 'Could not support setting attributes from ' - + f'{m21Object} error in self.m21toLy,' - + ' missing class definitions and no "*"') + f'{m21Object} error in self.m21toLy,' + ' missing class definitions and no "*"' + ) classDict = self.m21toLy[classLookup] for m21Attribute in classDict: try: diff --git a/music21/lily/translate.py b/music21/lily/translate.py index ce89f22a5e..f15561851b 100644 --- a/music21/lily/translate.py +++ b/music21/lily/translate.py @@ -597,7 +597,7 @@ def getLySpacersFromStream(self, streamIn, measuresOnly=True): dur = str(self.lyMultipliedDurationFromDuration(el.duration)) returnString = returnString + 's' + dur # general exception is the only way to catch str exceptions - except Exception: + except Exception: # pylint: disable=bare-except for c in el.duration.components: dur = str(self.lyMultipliedDurationFromDuration(c)) returnString = returnString + 's' + dur diff --git a/music21/metadata/bundles.py b/music21/metadata/bundles.py index f0a6abd784..dd37a50830 100644 --- a/music21/metadata/bundles.py +++ b/music21/metadata/bundles.py @@ -1118,7 +1118,7 @@ def read(self, filePath=None): if not filePath.exists(): environLocal.printDebug( f'no metadata found for: {self.name!r}; ' - + f'try building cache with corpus.cacheMetadata({self.name!r})' + f'try building cache with corpus.cacheMetadata({self.name!r})' ) return self diff --git a/music21/metadata/caching.py b/music21/metadata/caching.py index 1f1e4d758f..01b4efe1bd 100644 --- a/music21/metadata/caching.py +++ b/music21/metadata/caching.py @@ -157,7 +157,7 @@ def parseNonOpus(self, parsedObject): else: environLocal.printDebug( 'addFromPaths: got stream without metadata, ' - + f'creating stub: {common.relativepath(str(self.cleanFilePath))}' + f'creating stub: {common.relativepath(str(self.cleanFilePath))}' ) metadataEntry = metadata.bundles.MetadataEntry( sourcePath=self.cleanFilePath, @@ -168,7 +168,7 @@ def parseNonOpus(self, parsedObject): except Exception: # wide catch is fine. pylint: disable=broad-exception-caught environLocal.warn( 'Had a problem with extracting metadata ' - + f'for {self.filePath}, piece ignored' + f'for {self.filePath}, piece ignored' ) environLocal.warn(traceback.format_exc()) @@ -185,8 +185,8 @@ def parseOpus(self, parsedObject): except Exception as exception: # wide catch is fine. pylint: disable=broad-exception-caught environLocal.warn( 'Had a problem with extracting metadata for score ' - + f'{scoreNumber} in {self.filePath}, whole opus ignored: ' - + f'{exception}' + f'{scoreNumber} in {self.filePath}, whole opus ignored: ' + f'{exception}' ) environLocal.printDebug(traceback.format_exc()) # Create a dummy metadata entry, representing the entire opus. diff --git a/music21/meter/base.py b/music21/meter/base.py index 9fa35534ac..b08158e003 100644 --- a/music21/meter/base.py +++ b/music21/meter/base.py @@ -2000,7 +2000,7 @@ def getOffsetFromBeat(self, beat): if beatInt - 1 > len(self.beatSequence) - 1: raise TimeSignatureException( f'requested beat value ({beatInt}) not found in beat partitions ' - + f'({self.beatSequence}) of ts {self}' + f'({self.beatSequence}) of ts {self}' ) # get a duration object for the beat; will translate into quarterLength # beat int counts from 1; subtract 1 to get index diff --git a/music21/meter/core.py b/music21/meter/core.py index 1541e2817a..6fb86efb1e 100644 --- a/music21/meter/core.py +++ b/music21/meter/core.py @@ -524,7 +524,7 @@ def __setitem__(self, key: int, value: MeterTerminal): # comparison of numerator and denominator if not isinstance(value, MeterTerminal): raise MeterException('values in MeterSequences must be MeterTerminals or ' - + f'MeterSequences, not {value}') + f'MeterSequences, not {value}') if value.ratioEqual(self[key]): self._partition[key] = value else: @@ -1374,8 +1374,8 @@ def weight(self, value: int | float) -> None: except TypeError as te: raise MeterException( 'Something wrong with the type of ' - + f'this numerator {self._numerator} {type(self._numerator)} ' - + f'or this denominator {self._denominator} {type(self._denominator)}' + f'this numerator {self._numerator} {type(self._numerator)} ' + f'or this denominator {self._denominator} {type(self._denominator)}' ) from te for mt in self._partition: @@ -1856,7 +1856,7 @@ def offsetToIndex(self, qLenPos, includeCoincidentBoundaries=False) -> int: if qLenPos >= self.duration.quarterLength or qLenPos < 0: raise MeterException( f'cannot access from qLenPos {qLenPos} ' - + f'where total duration is {self.duration.quarterLength}' + f'where total duration is {self.duration.quarterLength}' ) qPos = 0 @@ -1971,7 +1971,7 @@ def offsetToSpan(self, qLenPos, permitMeterModulus=False): # 'self.duration', self.duration]) raise MeterException( f'cannot access qLenPos {qLenPos} when total duration is ' - + f'{self.duration.quarterLength} and ts is {self}' + f'{self.duration.quarterLength} and ts is {self}' ) # environLocal.printDebug(['offsetToSpan', 'got qLenPos old', qLenPos]) @@ -2009,7 +2009,7 @@ def offsetToWeight(self, qLenPos): if qLenPos >= self.duration.quarterLength or qLenPos < 0: raise MeterException( f'cannot access qLenPos {qLenPos} when total duration is ' - + f'{self.duration.quarterLength} and ts is {self}' + f'{self.duration.quarterLength} and ts is {self}' ) iMatch = self.offsetToIndex(qLenPos) return opFrac(self[iMatch].weight) diff --git a/music21/meter/tools.py b/music21/meter/tools.py index 014abbb653..e7bc7126b1 100644 --- a/music21/meter/tools.py +++ b/music21/meter/tools.py @@ -156,10 +156,10 @@ def slashMixedToFraction(valueSrc: str) -> tuple[NumDenomTuple, bool]: except ValueError: raise Music21Exception( 'Cannot parse this file -- this error often comes ' - + 'up if the musicxml pickled file is out of date after a change ' - + 'in musicxml/__init__.py . ' - + 'Clear your temp directory of .p and .p.gz files and try again. ' - + f'Time Signature: {valueSrc} ') + 'up if the musicxml pickled file is out of date after a change ' + 'in musicxml/__init__.py . ' + 'Clear your temp directory of .p and .p.gz files and try again. ' + f'Time Signature: {valueSrc} ') post: list[NumDenom] = [] # when encountering a missing denominator, find the first defined diff --git a/music21/musicxml/m21ToXml.py b/music21/musicxml/m21ToXml.py index 3d650e08ca..a5016a7e3d 100644 --- a/music21/musicxml/m21ToXml.py +++ b/music21/musicxml/m21ToXml.py @@ -413,7 +413,7 @@ def fromGeneralObject(self, obj: prebase.ProtoM21Object): if outObj is None: raise MusicXMLExportException( 'Cannot translate the object ' - + f'{self.generalObj} to a complete musicXML document; put it in a Stream first!' + f'{self.generalObj} to a complete musicXML document; put it in a Stream first!' ) return outObj @@ -6907,7 +6907,7 @@ def beamToXml(self, beamObject): else: raise MusicXMLExportException( 'partial beam defined without a proper direction set ' - + f'(set to {beamObject.direction})' + f'(set to {beamObject.direction})' ) else: raise MusicXMLExportException( diff --git a/music21/musicxml/xmlToM21.py b/music21/musicxml/xmlToM21.py index 298462ba00..75288d8a00 100644 --- a/music21/musicxml/xmlToM21.py +++ b/music21/musicxml/xmlToM21.py @@ -1165,10 +1165,10 @@ def partGroups(self): staffGroup.addSpannedElements(self.m21PartObjectsById[partIdTest]) foundOne = True - if foundOne is False: + if not foundOne: raise MusicXMLImportException( 'Cannot find part in m21PartObjectsById dictionary by Id:' - + f' {ke} \n Full Dict:\n {self.m21PartObjectsById!r} ') + f' {ke} \n Full Dict:\n {self.m21PartObjectsById!r} ') mxPartGroup = pgObj.mxPartGroup seta(staffGroup, mxPartGroup, 'group-name', 'name') # TODO: group-name-display diff --git a/music21/note.py b/music21/note.py index 7a56c69bf0..c6dd5c1bce 100644 --- a/music21/note.py +++ b/music21/note.py @@ -351,7 +351,7 @@ def syllabic(self, newSyllabic: SyllabicChoices): if newSyllabic not in SYLLABIC_CHOICES: raise LyricException( f'Syllabic value {newSyllabic!r} is not in ' - + f'note.SYLLABIC_CHOICES, namely: {SYLLABIC_CHOICES}' + f'note.SYLLABIC_CHOICES, namely: {SYLLABIC_CHOICES}' ) self._syllabic = newSyllabic diff --git a/music21/pitch.py b/music21/pitch.py index c78bc2388c..acb47ed56a 100644 --- a/music21/pitch.py +++ b/music21/pitch.py @@ -3713,7 +3713,7 @@ def harmonicFromFundamental(self, if target.ps <= fundamental.ps: raise PitchException( 'cannot find an equivalent harmonic for a fundamental ' - + f'({fundamental}) that is not above this Pitch ({self})' + f'({fundamental}) that is not above this Pitch ({self})' ) # up to the 32 harmonic diff --git a/music21/repeat.py b/music21/repeat.py index 424a1dc9f2..17bc473e51 100644 --- a/music21/repeat.py +++ b/music21/repeat.py @@ -942,12 +942,12 @@ def repeatBarsAreCoherent(self): if startCount not in (endCount, endCount - 1): environLocal.printDebug([ 'start count not the same as end count: ' - + f'{startCount} / {endCount}' + f'{startCount} / {endCount}' ]) return False # environLocal.printDebug([ # 'matched start and end repeat barline count of: ' - # + f'{startCount}/{endCount}' + # f'{startCount}/{endCount}' # ]) return True diff --git a/music21/roman.py b/music21/roman.py index 25bdf7eb2e..43f23238d5 100644 --- a/music21/roman.py +++ b/music21/roman.py @@ -1237,8 +1237,8 @@ def romanNumeralFromChord( except fbNotation.ModifierException as strerror: # pragma: no cover raise RomanNumeralException( 'Could not parse ' - + f'{rnString} from chord {chordObj} as an RN ' - + f'in key {keyObj}: {strerror}' + f'{rnString} from chord {chordObj} as an RN ' + f'in key {keyObj}: {strerror}' ) from strerror # Is this linking them in an unsafe way? @@ -3474,8 +3474,8 @@ def key(self, keyOrScale): except AttributeError: # pragma: no cover raise RomanNumeralException( 'Cannot call classes on object ' - + f'{keyOrScale!r}, send only Key ' - + 'or Scale Music21Objects' + f'{keyOrScale!r}, send only Key ' + 'or Scale Music21Objects' ) if 'Key' in keyClasses: # good to go diff --git a/music21/romanText/rtObjects.py b/music21/romanText/rtObjects.py index 0e742ae16b..1dd89acf76 100644 --- a/music21/romanText/rtObjects.py +++ b/music21/romanText/rtObjects.py @@ -826,7 +826,7 @@ def getOffset(self, timeSignature): except exceptions21.TimeSignatureException: environLocal.printDebug([ 'bad beat specification: ' - + f'{self.src} in a meter of {timeSignature}' + f'{self.src} in a meter of {timeSignature}' ]) post = 0.0 @@ -1171,7 +1171,7 @@ def tokenizeBody(self, lines): tracebackMessage = traceback.format_exc() raise RTHandlerException( f'At line {currentLineNumber} ({line}) an exception was raised:\n' - + f'{tracebackMessage}' + f'{tracebackMessage}' ) from exc return post diff --git a/music21/romanText/translate.py b/music21/romanText/translate.py index 2cb9526fd2..c2a9e14cdb 100644 --- a/music21/romanText/translate.py +++ b/music21/romanText/translate.py @@ -267,9 +267,9 @@ def _copyMultipleMeasures(rtMeasure: rtObjects.RTMeasure, except TypeError as te: # pragma: no cover raise RomanTextTranslateException( f'Failed to copy measure {mPast.number} to measure range ' - + f'{targetStart}-{targetEnd}: did you perhaps parse an RTOpus ' - + 'object with romanTextToStreamScore instead of ' - + 'romanTextToStreamOpus?' + f'{targetStart}-{targetEnd}: did you perhaps parse an RTOpus ' + 'object with romanTextToStreamScore instead of ' + 'romanTextToStreamOpus?' ) from te m.number = rtMeasure.number[0] + mPast.number - targetStart measures.append(m) @@ -386,7 +386,7 @@ def translateTokens(self, tokens): tracebackMessage = traceback.format_exc() raise RomanTextTranslateException( f'At line {token.lineNumber} for token {token}, ' - + f'an exception was raised: \n{tracebackMessage}') from exc + f'an exception was raised: \n{tracebackMessage}') from exc p = self.p p.coreElementsChanged() diff --git a/music21/search/base.py b/music21/search/base.py index b11f91eddb..3c07c33075 100644 --- a/music21/search/base.py +++ b/music21/search/base.py @@ -1075,7 +1075,7 @@ def mostCommonMeasureRhythms(streamIn, transposeDiatonic=False): ... measures = in_dict['measures'] ... print( ... f'no: {number} ' - ... + f'rhythmString: {rhythmString}' + ... f'rhythmString: {rhythmString}' ... ) ... bars = [ ... (m.number, str(m.getContextByClass(stream.Part).id)) diff --git a/music21/search/lyrics.py b/music21/search/lyrics.py index a873e668b9..6b1e89856e 100644 --- a/music21/search/lyrics.py +++ b/music21/search/lyrics.py @@ -54,10 +54,11 @@ class IndexedLyric(namedtuple( 'absoluteStart': '''the position, not in the current identifier, but in all the lyrics''', 'absoluteEnd': '''the end position in all the lyrics''' } + def __repr__(self): return (f'IndexedLyric(el={self.el!r}, start={self.start!r}, end={self.end!r}, ' - + f'measure={self.measure!r}, lyric={self.lyric!r}, text={self.text!r}, ' - + f'identifier={self.identifier!r})') + f'measure={self.measure!r}, lyric={self.lyric!r}, text={self.text!r}, ' + f'identifier={self.identifier!r})') def modify(self, **keywords): ''' @@ -101,8 +102,8 @@ class SearchMatch(namedtuple('SearchMatch', def __repr__(self): return (f'SearchMatch(mStart={self.mStart!r}, mEnd={self.mEnd!r}, ' - + f'matchText={self.matchText!r}, els={self.els!r}, indices=[...], ' - + f'identifier={self.identifier!r})') + f'matchText={self.matchText!r}, els={self.els!r}, indices=[...], ' + f'identifier={self.identifier!r})') class LyricSearcherException(Music21Exception): diff --git a/music21/sites.py b/music21/sites.py index 1da83fcb3f..a07d903848 100644 --- a/music21/sites.py +++ b/music21/sites.py @@ -357,7 +357,7 @@ def add(self, obj, timeValue=None, idKey=None, classString=None): # if idKey is not None: # print( # 'Updating idKey ' - # + f'{idKey} for object {id(obj)}' + # f'{idKey} for object {id(obj)}' # ) # environLocal.printDebug(['adding obj', obj, idKey]) @@ -966,7 +966,7 @@ def remove(self, site): except Exception as e: raise SitesException( 'an entry for this object ' - + f'({site}) is not stored in this Sites object' + f'({site}) is not stored in this Sites object' ) from e def removeById(self, idKey): diff --git a/music21/spanner.py b/music21/spanner.py index fbf44aabfd..ddc158865d 100644 --- a/music21/spanner.py +++ b/music21/spanner.py @@ -464,9 +464,9 @@ def addSpannedElements( # it makes sense to not have multiple copies # environLocal.printDebug([ # 'attempting to add an object ' - # + f'({c}) that is already found in the SpannerStorage stream ' - # + f'of spanner {self};\n' - # + 'this may not be an error.' + # f'({c}) that is already found in the SpannerStorage stream ' + # f'of spanner {self};\n' + # 'this may not be an error.' # ]) self.spannerStorage.coreElementsChanged() diff --git a/music21/stream/base.py b/music21/stream/base.py index 5f4f5936cd..88b6c76bb5 100644 --- a/music21/stream/base.py +++ b/music21/stream/base.py @@ -671,7 +671,7 @@ def __getitem__(self, except IndexError as ie: raise IndexError( f'attempting to access index {k} ' - + f'while elements is of size {len(self.elements)}' + f'while elements is of size {len(self.elements)}' ) from ie # setting active site as cautionary measure self.coreSelfActiveSite(match) @@ -2188,7 +2188,7 @@ def elementOffset(self, element, returnSpecial=False): except AttributeError as ae: # pragma: no cover raise base.SitesException( 'attempted to retrieve a bound offset with a string ' - + f'attribute that is not supported: {o}') from ae + f'attribute that is not supported: {o}') from ae else: return o @@ -6400,8 +6400,8 @@ def chordifyOneMeasure(templateInner, streamToChordify): if quarterLength < 0: # pragma: no cover environLocal.warn( 'Something is wrong with the verticality ' - + f'in stream {templateInner!r}: {vert!r} ' - + f'its endTime {endTime} is less than its offset {offset}' + f'in stream {templateInner!r}: {vert!r} ' + f'its endTime {endTime} is less than its offset {offset}' ) chordOrRest = vert.makeElement(quarterLength, @@ -9641,7 +9641,7 @@ def sliceByQuarterLengths(self, quarterLengthList, *, target=None, if not opFrac(sum(qlProcess)) == e.quarterLength: raise StreamException( 'cannot map quarterLength list into element Duration: ' - + f'{sum(qlProcess)}, {e.quarterLength}' + f'{sum(qlProcess)}, {e.quarterLength}' ) post = e.splitByQuarterLengths(qlProcess, addTies=addTies) diff --git a/music21/stream/core.py b/music21/stream/core.py index 4570ad3362..33748bd648 100644 --- a/music21/stream/core.py +++ b/music21/stream/core.py @@ -426,7 +426,7 @@ def coreGuardBeforeAddElement(self, element, *, checkRedundancy=True): if eInStream is element: raise StreamException( f'the object ({element!r}, id()={id(element)} ' - + f'is already found in this Stream ({self!r}, id()={id(self)})' + f'is already found in this Stream ({self!r}, id()={id(self)})' ) # something was old. delete from _offsetDict # environLocal.warn('stale object') diff --git a/music21/stream/makeNotation.py b/music21/stream/makeNotation.py index f3407bb2a7..4b5d891d16 100644 --- a/music21/stream/makeNotation.py +++ b/music21/stream/makeNotation.py @@ -196,8 +196,8 @@ def makeBeams( if durSum > barQL: # environLocal.printDebug([ # 'attempting makeBeams with a bar that contains durations ' - # + 'that sum greater than bar duration ' - # + f'({durSum} > {barQL})' + # 'that sum greater than bar duration ' + # f'({durSum} > {barQL})' # ]) continue @@ -1306,8 +1306,8 @@ def makeTies( # TODO: put them entirely in the next measure. # raise stream.StreamException( # 'element ' - # + f'({e}) has offset {eOffset} within a measure ' - # + f'that ends at offset {mEnd}' + # f'({e}) has offset {eOffset} within a measure ' + # f'that ends at offset {mEnd}' # ) qLenWithinMeasure = mEnd - eOffset diff --git a/music21/tablature.py b/music21/tablature.py index 97189a2038..f730d6e894 100644 --- a/music21/tablature.py +++ b/music21/tablature.py @@ -228,8 +228,8 @@ def getPitches(self) -> list[None|pitch.Pitch]: if len(self.tuning) != self.numStrings: raise TablatureException( 'Tuning must be set first, tuned for ' - + f'{len(self.tuning)} notes, on a ' - + f'{self.numStrings} string instrument' + f'{len(self.tuning)} notes, on a ' + f'{self.numStrings} string instrument' ) pitchList: list[pitch.Pitch|None] = [None] * self.numStrings diff --git a/music21/tempo.py b/music21/tempo.py index e51560351a..10da94d87b 100644 --- a/music21/tempo.py +++ b/music21/tempo.py @@ -1259,7 +1259,7 @@ def interpolateElements(element1, element2, sourceStream, >>> destStream2.insert(50.5, element2) >>> tempo.interpolateElements(element1, element2, sourceStream, destStream2) >>> for el in [eA, eB, eC]: - ... offset = el.getOffsetBySite(destStream2) + ... offset = float(el.getOffsetBySite(destStream2)) ... print(f'{offset:.1f}') 20.2 30.3 @@ -1275,6 +1275,8 @@ def interpolateElements(element1, element2, sourceStream, Traceback (most recent call last): music21.tempo.TempoException: Could not find element with id ... ''' + # TODO: when python 3.13 is the minimum, get rid of the float around el.getOffsetBySite + # in the doctest above try: startOffsetSrc = element1.getOffsetBySite(sourceStream) except exceptions21.Music21Exception as e: @@ -1310,8 +1312,9 @@ def interpolateElements(element1, element2, sourceStream, else: raise TempoException( 'Could not find element ' - + f'{el!r} with id {el.id!r} ' - + 'in destinationStream and autoAdd is false') from e + f'{el!r} with id {el.id!r} ' + 'in destinationStream and autoAdd is false' + ) from e else: destinationOffset = (scaleAmount * (elOffsetSrc - startOffsetSrc)) + startOffsetDest el.setOffsetBySite(destinationStream, destinationOffset) diff --git a/music21/test/multiprocessTest.py b/music21/test/multiprocessTest.py index 8ab58ccb9f..a63251a484 100644 --- a/music21/test/multiprocessTest.py +++ b/music21/test/multiprocessTest.py @@ -245,13 +245,13 @@ def printSummary(summaryOutput, timeStart, pathsToRun): elif moduleResponse.returnCode == 'TrappedException': otherSummary.append( f'Trapped Exception for module {moduleResponse.moduleName}, ' - + f'at {moduleResponse.fp}: ' - + f'{moduleResponse.testRunner}' + f'at {moduleResponse.fp}: ' + f'{moduleResponse.testRunner}' ) elif moduleResponse.returnCode == 'LargeException': otherSummary.append( f'Large Exception for file {moduleResponse.fp}: ' - + f'{moduleResponse.testResult}' + f'{moduleResponse.testResult}' ) elif moduleResponse.returnCode == 'ImportError': otherSummary.append(f'Import Error for {moduleResponse.fp}') @@ -263,8 +263,8 @@ def printSummary(summaryOutput, timeStart, pathsToRun): if moduleResponse.success: successSummary.append( f'{moduleResponse.moduleName} successfully ran ' - + f'{moduleResponse.testsRun} tests in ' - + f'{moduleResponse.runTime} seconds' + f'{moduleResponse.testsRun} tests in ' + f'{moduleResponse.runTime} seconds' ) else: errorsList = moduleResponse.errors @@ -272,12 +272,12 @@ def printSummary(summaryOutput, timeStart, pathsToRun): failuresList = moduleResponse.failures errorsFoundSummary.append( '\n-----------------------------\n' - + f'{moduleResponse.moduleName} had ' - + f'{len(errorsList)} ERRORS and ' - + f'{len(failuresList)} FAILURES in ' - + f'{moduleResponse.testsRun} tests after ' - + f'{moduleResponse.runTime} seconds:\n' - + '-----------------------------\n' + f'{moduleResponse.moduleName} had ' + f'{len(errorsList)} ERRORS and ' + f'{len(failuresList)} FAILURES in ' + f'{moduleResponse.testsRun} tests after ' + f'{moduleResponse.runTime} seconds:\n' + '-----------------------------\n' ) for e in errorsList: outStr += e + '\n' diff --git a/music21/test/testRunner.py b/music21/test/testRunner.py index 519be56bc9..38e1954cb8 100644 --- a/music21/test/testRunner.py +++ b/music21/test/testRunner.py @@ -252,8 +252,7 @@ def testHello(self): optionflags=optionflags, ) except ValueError as ve: # no docstrings - print('Problem in docstrings [usually a missing r value before ' - + f'the quotes:] {ve}') + print(f'Problem in docstrings [usually a missing r value before the quotes]: {ve}') s1 = unittest.TestSuite() verbosity = 1 diff --git a/music21/tinyNotation.py b/music21/tinyNotation.py index d2ffd3dd94..591fca9d08 100644 --- a/music21/tinyNotation.py +++ b/music21/tinyNotation.py @@ -1523,7 +1523,7 @@ def testGetDefaultTokenMap(self) -> None: validTokenTypeCounts, ( 'Found unexpected token type in default token map:' - + f'{tokenType.__class__.__name__}.' + f'{tokenType.__class__.__name__}.' ) ) @@ -1534,8 +1534,8 @@ def testGetDefaultTokenMap(self) -> None: 0, ( 'Should provide a non-empty string for the regular ' - + 'expression in the default token map for tokens of type ' - + f'{tokenType.__class__.__name__}.' + 'expression in the default token map for tokens of type ' + f'{tokenType.__class__.__name__}.' ) ) diff --git a/music21/tree/timespanTree.py b/music21/tree/timespanTree.py index 905b15605d..78a791c11b 100644 --- a/music21/tree/timespanTree.py +++ b/music21/tree/timespanTree.py @@ -372,8 +372,7 @@ def iterateConsonanceBoundedVerticalities(self): ... for verticality in subsequence: ... verticalityChord = verticality.toChord() ... print(f'\t[{verticality.measureNumber}] ' - ... + f'{verticality}: {verticalityChord.isConsonant()}') - ... + ... f'{verticality}: {verticalityChord.isConsonant()}') Subsequence: [2] : True [2] : False diff --git a/music21/tree/toStream.py b/music21/tree/toStream.py index 38d617f996..6aea30cb1e 100644 --- a/music21/tree/toStream.py +++ b/music21/tree/toStream.py @@ -94,7 +94,8 @@ def chordified(timespans, templateStream=None): # pragma: no cover if quarterLength < 0: raise TreeException( 'Something is wrong with the verticality ' - + f'{vert!r} its endTime {endTime:f} is less than its offset {offset:f}') + f'{vert!r} its endTime {endTime:f} is less than its offset {offset:f}' + ) element = vert.makeElement(quarterLength) measureList[measureIndex].append(element) return outputStream @@ -107,7 +108,8 @@ def chordified(timespans, templateStream=None): # pragma: no cover if quarterLength < 0: raise TreeException( 'Something is wrong with the verticality ' - + f'{vert!r}, its endTime {endTime:f} is less than its offset {offset:f}') + f'{vert!r}, its endTime {endTime:f} is less than its offset {offset:f}' + ) element = vert.makeElement(quarterLength) elements.append(element) diff --git a/music21/voiceLeading.py b/music21/voiceLeading.py index 30b0b405b0..ca3b11334a 100644 --- a/music21/voiceLeading.py +++ b/music21/voiceLeading.py @@ -205,7 +205,7 @@ def key(self, keyValue): except AttributeError as ae: # pragma: no cover raise VoiceLeadingQuartetException( 'got a key signature that is not a string or music21 Key ' - + f'object: {keyValue}' + f'object: {keyValue}' ) from ae self._key = keyValue From 36330e5a1c4323ab164a806091c6ccb0c5d0cd97 Mon Sep 17 00:00:00 2001 From: Michael Scott Asato Cuthbert Date: Fri, 2 Jan 2026 22:52:32 -1000 Subject: [PATCH 13/13] lint-lint --- music21/lily/translate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/music21/lily/translate.py b/music21/lily/translate.py index f15561851b..ec06edd076 100644 --- a/music21/lily/translate.py +++ b/music21/lily/translate.py @@ -597,7 +597,7 @@ def getLySpacersFromStream(self, streamIn, measuresOnly=True): dur = str(self.lyMultipliedDurationFromDuration(el.duration)) returnString = returnString + 's' + dur # general exception is the only way to catch str exceptions - except Exception: # pylint: disable=bare-except + except Exception: # pylint: disable=broad-exception-caught for c in el.duration.components: dur = str(self.lyMultipliedDurationFromDuration(c)) returnString = returnString + 's' + dur