From 9050d1308a46ce0299649fa4ea593cdeaad13fc2 Mon Sep 17 00:00:00 2001 From: Myke Cuthbert Date: Tue, 19 Apr 2022 12:39:34 -1000 Subject: [PATCH 1/3] Remove support for Py3.7; add some 3.8+ only feat. --- .github/workflows/maincheck.yml | 4 +-- music21/__init__.py | 9 ++++--- music21/audioSearch/__init__.py | 10 ++++---- music21/braille/segment.py | 44 +++++++++++++++------------------ music21/duration.py | 27 ++++++++++---------- music21/roman.py | 11 +++------ music21/stream/iterator.py | 43 +++++++++++++++++++++++--------- music21/test/coverageM21.py | 2 +- music21/tinyNotation.py | 10 +++++--- music21/tree/fromStream.py | 5 ++-- music21/voiceLeading.py | 4 --- setup.py | 2 +- 12 files changed, 91 insertions(+), 80 deletions(-) diff --git a/.github/workflows/maincheck.yml b/.github/workflows/maincheck.yml index 72f6fca5fc..eb18b3c026 100644 --- a/.github/workflows/maincheck.yml +++ b/.github/workflows/maincheck.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: [3.7, 3.8, 3.9, "3.10"] + python-version: [3.8, 3.9, "3.10"] steps: - uses: actions/setup-python@v2 with: @@ -27,7 +27,7 @@ jobs: - name: Run Main Test script run: python -c 'from music21.test.testSingleCoreAll import ciMain as ci; ci()' - name: Coveralls - if: ${{ matrix.python-version == '3.7' }} + if: ${{ matrix.python-version == '3.8' }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} COVERALLS_SERVICE_NAME: github diff --git a/music21/__init__.py b/music21/__init__.py index f480f650bf..aa14cfca49 100644 --- a/music21/__init__.py +++ b/music21/__init__.py @@ -37,17 +37,18 @@ ''' import sys -minPythonVersion = (3, 7) +minPythonVersion = (3, 8) minPythonVersionStr = '.'.join([str(x) for x in minPythonVersion]) if sys.version_info < minPythonVersion: # DO NOT CHANGE THIS TO AN f-String -- it needs to run on old python. raise ImportError(''' - Music21 v.7.0+ is a Python {}+ only library. + Music21 v.8.0+ is a Python {}+ only library. Use music21 v1 to run on Python 2.1-2.6. Use music21 v4 to run on Python 2.7. Use music21 v5.1 to run on Python 3.4. Use music21 v5.7 to run on Python 3.5. Use music21 v6.7 to run on Python 3.6. + Use music21 v7.3 to run on Python 3.7 If you have the wrong version there are several options for getting the right one. @@ -173,7 +174,7 @@ from music21 import prebase # noqa: E402 from music21 import sites # noqa: E402 -# should this simply be from music21.base import * since __all__ is well defined? +# should this simply be from music21.base import * since __all__ is well-defined? from music21.base import Music21Exception # noqa: E402 from music21.base import SitesException # noqa: E402 from music21.base import Music21ObjectException # noqa: E402 @@ -192,7 +193,7 @@ from music21.test.testRunner import mainTest # noqa: E402 # ----------------------------------------------------------------------------- -# now import all modules so they are accessible from "import music21" +# now import all modules to make them accessible from "import music21" from music21 import abcFormat # noqa: E402 from music21 import alpha # noqa: E402 from music21 import analysis # noqa: E402 diff --git a/music21/audioSearch/__init__.py b/music21/audioSearch/__init__.py index f8285e4202..d392a5e3bb 100644 --- a/music21/audioSearch/__init__.py +++ b/music21/audioSearch/__init__.py @@ -70,7 +70,7 @@ def histogram(data, bins): # noinspection PyShadowingNames ''' Partition the list in `data` into a number of bins defined by `bins` - and return the number of elements in each bins and a set of `bins` + 1 + and return the number of elements in each bin and a set of `bins` + 1 elements where the first element (0) is the start of the first bin, the last element (-1) is the end of the last bin, and every remaining element (i) is the dividing point between one bin and another. @@ -552,7 +552,7 @@ def smoothFrequencies( 220 Different levels of smoothing have different effects. At smoothLevel=2, - the isolated 220hz sample is pulling down the samples around it: + the isolated 220hz sample is pulling down the surrounding samples: >>> audioSearch.smoothFrequencies(inputPitches, smoothLevels=2)[:5] [330, 275, 358, 399, 420] @@ -813,7 +813,7 @@ def notesAndDurationsToStream( ''' take a list of :class:`~music21.note.Note` objects or rests and an equally long list of how long - each ones lasts in terms of samples and returns a + each one lasts in terms of samples and returns a Stream using the information from quarterLengthEstimation and quantizeDurations. @@ -969,11 +969,11 @@ def decisionProcess( countdown = countdown + 1 elif dist > 20 and countdown == 0: countdown += 1 - environLocal.printDebug(f'Excessive distance....? dist={dist}') # 3.8 replace {dist=} + environLocal.printDebug(f'Excessive distance....? {dist=}') elif dist > 30 and countdown == 1: countdown += 1 - environLocal.printDebug(f'Excessive distance....? dist={dist}') # 3.8 replace {dist=} + environLocal.printDebug(f'Excessive distance....? {dist=}') elif ((firstNotePage is not None and lastNotePage is not None) and ((positionBeginningData < firstNotePage diff --git a/music21/braille/segment.py b/music21/braille/segment.py index 20cfab6b0c..6eface8c63 100644 --- a/music21/braille/segment.py +++ b/music21/braille/segment.py @@ -20,8 +20,7 @@ import copy import enum import unittest - -from typing import Optional, Union +from typing import Optional, Union, TypedDict from music21 import bar from music21 import chord @@ -110,15 +109,11 @@ class Affinity(enum.IntEnum): layout.PageLayout, layout.StaffLayout] -# Uncomment when Python 3.8 is the minimum version -# from typing import TypedDict, Optional -# class GroupingGlobals(TypedDict): -# keySignature: Optional[key.KeySignature] -# timeSignature: Optional[meter.TimeSignature] -# GROUPING_GLOBALS: GroupingGlobals = {...} - +class GroupingGlobals(TypedDict): + keySignature: Optional[key.KeySignature] + timeSignature: Optional[meter.TimeSignature] -GROUPING_GLOBALS = { +GROUPING_GLOBALS: GroupingGlobals = { 'keySignature': None, # will be key.KeySignature(0) on first call 'timeSignature': None, # will be meter.TimeSignature('4/4') on first call } @@ -130,12 +125,8 @@ def setGroupingGlobals(): in Braille is run, but saves creating two expensive objects if never run ''' if GROUPING_GLOBALS['keySignature'] is None: - # remove noinspection when Python 3.8 is the minimum - # noinspection PyTypeChecker GROUPING_GLOBALS['keySignature'] = key.KeySignature(0) if GROUPING_GLOBALS['timeSignature'] is None: - # remove noinspection when Python 3.8 is the minimum - # noinspection PyTypeChecker GROUPING_GLOBALS['timeSignature'] = meter.TimeSignature('4/4') @@ -186,7 +177,7 @@ def __init__(self, *args): - These are the defaults and they are shared across all objects... + These are the defaults, and they are shared across all objects... >>> bg.keySignature @@ -236,7 +227,7 @@ def __getattr__(self, attr): def __str__(self): ''' - Return an unicode braille representation + Return a unicode braille representation of each object in the BrailleElementGrouping. ''' allObjects = [] @@ -300,7 +291,7 @@ class BrailleSegment(text.BrailleText): def __init__(self, lineLength: int = 40): ''' A segment is "a group of measures occupying more than one braille line." - Music is divided into segments so as to "present the music to the reader + Music is divided into segments in order to "present the music to the reader in a meaningful manner and to give him convenient reference points to use in memorization" (BMTM, 71). @@ -441,14 +432,14 @@ def __str__(self): def transcribe(self): ''' - transcribes all of the noteGroupings in this dict by: + Transcribes all noteGroupings in this dict by: - first transcribing the Heading (if applicable) - then the Measure Number - then adds appropriate numbers of dummyRests - then adds the Rest of the Note Groupings + * First transcribes the Heading (if applicable) + * then the Measure Number + * then adds appropriate numbers of dummyRests + * then adds the Rest of the Note Groupings - returns brailleText + Returns brailleText ''' # noinspection PyAttributeOutsideInit self.groupingKeysToProcess = list(sorted(self.keys())) @@ -922,6 +913,7 @@ def extractTempoTextGrouping(self): self.extractMeasureNumber() def consolidate(self): + # noinspection PyShadowingNames ''' Puts together certain types of elements according to the last digit of their key (if it is the same as Affinity.NOTEGROUP or not. @@ -1126,6 +1118,7 @@ def __str__(self): return out def yieldCombinedGroupingKeys(self): + # noinspection PyShadowingNames ''' yields all the keys in order as a tuple of (rightKey, leftKey) where two keys are grouped if they have the same segmentKey except for the hand. @@ -1174,7 +1167,8 @@ def matchOther(thisKey_inner, otherKey): yield(thisKey, storedLeft) elif (thisKey.affinity == Affinity.NOTEGROUP and matchOther(thisKey._replace(affinity=Affinity.INACCORD), storedLeft)): - # r.h. notegroup goes before an lh inaccord, despite this being out of order + # r.h. notegroup goes before an l.h. inaccord, + # despite this being out of order yield(thisKey, storedLeft) else: yield(None, storedLeft) @@ -1400,6 +1394,7 @@ def findSegments(music21Part, suppressOctaveMarks=False, upperFirstInNoteFingering=True, ): + # noinspection PyShadowingNames ''' Takes in a :class:`~music21.stream.Part`. @@ -1745,6 +1740,7 @@ def getRawSegments(music21Part, setHand=None, maxLineLength: int = 40, ): + # noinspection PyShadowingNames ''' Takes in a :class:`~music21.stream.Part`, divides it up into segments (i.e. instances of :class:`~music21.braille.segment.BrailleSegment`). This function assumes diff --git a/music21/duration.py b/music21/duration.py index 0b268dab31..d7fd04a1b6 100644 --- a/music21/duration.py +++ b/music21/duration.py @@ -52,7 +52,7 @@ import io import unittest from math import inf, isnan -from typing import Union, Tuple, Dict, List, Optional, Iterable +from typing import Union, Tuple, Dict, List, Optional, Iterable, Literal from collections import namedtuple @@ -268,7 +268,7 @@ def quarterLengthToClosestType(qLen: OffsetQLIn): >>> duration.quarterLengthToClosestType(1.8) ('quarter', False) - Some very very close types will return True for exact conversion... + Some extremely close types will return True for exact conversion... >>> duration.quarterLengthToClosestType(2.0000000000000001) ('half', True) @@ -335,8 +335,9 @@ def convertQuarterLengthToType(qLen: OffsetQLIn) -> str: f'cannot convert quarterLength {qLen} exactly to type') return durationType -# TODO: in Py3.8+ Union[Tuple[int, str], Tuple[Literal[False], Literal[False]]] -def dottedMatch(qLen: OffsetQLIn, maxDots=4) -> Union[Tuple[int, str], Tuple[bool, bool]]: +def dottedMatch(qLen: OffsetQLIn, + maxDots=4 + ) -> Union[Tuple[int, str], Tuple[Literal[False], Literal[False]]]: ''' Given a quarterLength, determine if there is a dotted (or non-dotted) type that exactly matches. Returns a pair of @@ -385,7 +386,7 @@ def quarterLengthToNonPowerOf2Tuplet( power of 2 denominator (such as 7:6) that represents the quarterLength and the DurationTuple that should be used to express the note. - This could be a double dotted note, but also a tuplet... + This could be a double-dotted note, but also a tuplet... >>> duration.quarterLengthToNonPowerOf2Tuplet(7) (, DurationTuple(type='breve', dots=0, quarterLength=8.0)) @@ -410,7 +411,7 @@ def quarterLengthToNonPowerOf2Tuplet( elif qFrac.numerator > qFrac.denominator * 2: while qFrac.numerator > qFrac.denominator * 2: qFrac = qFrac / 2 - # qFrac will always be in lowest terms + # qFrac will always be expressed in lowest terms closestSmallerType, unused_match = quarterLengthToClosestType(qLen / qFrac.denominator) @@ -452,7 +453,7 @@ def quarterLengthToTuplet( ] - By specifying only 1 `maxToReturn`, the a single-length list containing the + By specifying only 1 `maxToReturn`, a single-length list containing the Tuplet with the smallest type will be returned. >>> duration.quarterLengthToTuplet(0.3333333, 1) @@ -504,7 +505,7 @@ def quarterConversion(qLen: OffsetQLIn) -> QuarterLengthConversion: Components is a tuple of DurationTuples (normally one) that add up to the qLen when multiplied by... - Tuplet is a single :class:`~music21.duration.Tuplet` that adjusts all of the components. + Tuplet is a single :class:`~music21.duration.Tuplet` that adjusts all components. (All quarterLengths can, technically, be notated as a single unit given a complex enough tuplet, as a last resort will look up to 199 as a tuplet type). @@ -587,7 +588,7 @@ def quarterConversion(qLen: OffsetQLIn) -> QuarterLengthConversion: tuplet=) A 4/7ths of a whole note, or - A quarter that is 4/7th of of a quarter + A quarter that is 4/7th of a quarter >>> duration.quarterConversion(4/7) QuarterLengthConversion(components=(DurationTuple(type='quarter', dots=0, quarterLength=1.0),), @@ -1408,7 +1409,7 @@ def durationActual(self, dA: Union[DurationTuple, 'Duration']): @property def durationNormal(self) -> DurationTuple: ''' - durationNormal is a DurationTuple that represents the notes that are + durationNormal is a DurationTuple that represents the notes that would be present in the space normally (if there were no tuplets). For instance, in a 7 dotted-eighth in the place of 2 double-dotted quarter notes tuplet, the durationNormal would be... @@ -2435,7 +2436,7 @@ def _updateQuarterLength(self): return if self._dotGroups == (0,) and not self.tuplets and len(self.components) == 1: - # do common tasks fast: + # make sure to do common tasks fast: self._qtrLength = self.components[0].quarterLength else: self._qtrLength = opFrac(self.quarterLengthNoTuplets * self.aggregateTupletMultiplier()) @@ -2943,7 +2944,7 @@ def aggregateTupletMultiplier(self) -> OffsetQL: Fraction(8, 15) ''' if not self.tuplets: - # do common cases fast. + # common cases should be fast. return 1.0 currentMultiplier = 1.0 @@ -3072,7 +3073,7 @@ def __init__(self, *arguments, **keywords): self.components = newComponents # set new components # make time is encoded in musicxml as divisions; here it can - # by a duration; but should it be the duration suggested by the grace? + # be encoded as a duration; but should it be the duration suggested by the grace? self._makeTime = False self._slash = None self.slash = True # can be True, False, or None; make None go to True? diff --git a/music21/roman.py b/music21/roman.py index dd98223b27..c7507d6ba0 100644 --- a/music21/roman.py +++ b/music21/roman.py @@ -17,10 +17,7 @@ import unittest import copy import re -from typing import Dict, Union, Optional, List, Tuple - -# when python 3.7 is removed from support: -# from typing import Literal +from typing import Dict, Union, Optional, List, Tuple, Literal from collections import namedtuple @@ -534,7 +531,7 @@ def figureTupleSolo( def identifyAsTonicOrDominant( inChord: Union[list, tuple, chord.Chord], inKey: key.Key -) -> Union[str, bool]: +) -> Union[str, Literal[False]]: ''' Returns the roman numeral string expression (either tonic or dominant) that best matches the inChord. Useful when you know inChord is either tonic or @@ -2693,9 +2690,7 @@ def _parseRNAloneAmidstAug6(self, workingFigure, useScale): secondary_tonic = self.secondaryRomanNumeralKey.tonic self.secondaryRomanNumeralKey = key.Key(secondary_tonic, 'minor') - # when Python 3.7 support is removed - # aug6type: Literal['It', 'Ger', 'Fr', 'Sw'] = aug6Match.group(1) - aug6type = aug6Match.group(1) + aug6type: Literal['It', 'Ger', 'Fr', 'Sw'] = aug6Match.group(1) if aug6type in ('It', 'Ger'): self.scaleDegree = 4 diff --git a/music21/stream/iterator.py b/music21/stream/iterator.py index dcb85c9089..acd1e1d2ab 100644 --- a/music21/stream/iterator.py +++ b/music21/stream/iterator.py @@ -15,7 +15,8 @@ StreamIterators are explicitly allowed to access private methods on streams. ''' import copy -from typing import TypeVar, List, Union, Callable, Optional, Dict +from typing import (TypeVar, List, Union, Callable, Optional, Literal, + Dict, TypedDict, TYPE_CHECKING) import unittest import warnings @@ -29,6 +30,9 @@ from music21.sites import SitesException +if TYPE_CHECKING: + import music21.stream + _SIter = TypeVar('_SIter') FilterType = Union[Callable, filters.StreamFilter] @@ -43,6 +47,17 @@ class StreamIteratorException(StreamException): class StreamIteratorInefficientWarning(PendingDeprecationWarning): pass + +class ActiveInformation(TypedDict, total=False): + # noinspection PyTypedDict + stream: Optional['music21.stream.Stream'] # https://youtrack.jetbrains.com/issue/PY-43689 + index: int + iterSection: Literal['_elements', '_endElements'] + sectionIndex: int + # noinspection PyTypedDict + lastYielded: Optional['music21.stream.Stream'] + + # ----------------------------------------------------------------------------- @@ -70,10 +85,16 @@ class StreamIterator(prebase.ProtoM21Object): False * StreamIterator.activeInformation -- a dict that contains information about where we are in the parse. Especially useful for recursive - streams. 'stream' = the stream that is currently active, 'index' - where in `.elements` we are, `iterSection` is `_elements` or `_endElements`, - and `sectionIndex` is where we are in the iterSection, or -1 if - we have not started. This dict is shared among all sub iterators. + streams: + + * `stream` = the stream that is currently active, + * `index` = where in `.elements` we are, + * `iterSection` is `_elements` or `_endElements`, + * `sectionIndex` is where we are in the iterSection, or -1 if + we have not started. + * `lastYielded` the stream that last yielded the element (present in + recursiveIterators only). + * (This dict is shared among all sub iterators.) Constructor keyword only arguments: @@ -105,7 +126,7 @@ def __init__(self, *, filterList: Union[List[FilterType], FilterType, None] = None, restoreActiveSites: bool = True, - activeInformation: Optional[Dict] = None, + activeInformation: Optional[ActiveInformation] = None, ignoreSorting: bool = False): if not ignoreSorting and srcStream.isSorted is False and srcStream.autoSort: srcStream.sort() @@ -119,7 +140,7 @@ def __init__(self, # this information can help in speed later self.elementsLength = len(self.srcStream._elements) self.sectionIndex = -1 # where we are within a given section (_elements or _endElements) - self.iterSection = '_elements' + self.iterSection: Literal['_elements', '_endElements'] = '_elements' self.cleanupOnStop = False self.restoreActiveSites: bool = restoreActiveSites @@ -148,7 +169,7 @@ def __init__(self, if activeInformation is not None: self.activeInformation = activeInformation else: - self.activeInformation = {} # in Py3.8 make a TypedDict + self.activeInformation: ActiveInformation = {} self.updateActiveInformation() def _reprInternal(self): @@ -174,7 +195,7 @@ def __call__(self) -> _SIter: Returns `self` without any changes. - TODO: manage and emit DeprecationWarnings in v.8 + TODO: manage and emit DeprecationWarnings in v.8 (probably impossible...) TODO: remove in v.9 ''' return self @@ -920,7 +941,7 @@ def getElementsByClass(self, classFilterList, *, returnClone=True): Add a filter to the Iterator to remove all elements except those that match one or more classes in the `classFilterList`. A single class - can also used for the `classFilterList` parameter instead of a List. + can also be used for the `classFilterList` parameter instead of a List. >>> s = stream.Stream(id='s1') >>> s.append(note.Note('C')) @@ -1120,7 +1141,7 @@ def getElementsByOffset( playing before the search but that end just before the end of the search type. See the code for allPlayingWhileSounding for a demonstration. - This chart, and the examples below, demonstrate the various + This chart, like the examples below, demonstrates the various features of getElementsByOffset. It is one of the most complex methods of music21 but also one of the most powerful, so it is worth learning at least the basics. diff --git a/music21/test/coverageM21.py b/music21/test/coverageM21.py index 75d9c86388..0ad03ec84f 100644 --- a/music21/test/coverageM21.py +++ b/music21/test/coverageM21.py @@ -35,7 +35,7 @@ def getCoverage(overrideVersion=False): if overrideVersion or sys.version_info.minor == 7: - # run on Py 3.7 -- to get Py 3.8/3.9 timing... + # run on Py 3.8 -- to get Py 3.9/3.10 timing... try: import coverage # type: ignore cov = coverage.Coverage(omit=omit_modules) diff --git a/music21/tinyNotation.py b/music21/tinyNotation.py index 107641c3db..24b2dfa02d 100644 --- a/music21/tinyNotation.py +++ b/music21/tinyNotation.py @@ -267,8 +267,8 @@ class State: >>> ts.autoExpires 2 ''' - # TODO in Python 3.8+: typing.Union[typing.Literal[False], int] - autoExpires: typing.Union[bool, int] = False # expires after N tokens or never. + # expires after N tokens or never. + autoExpires: typing.Union[typing.Literal[False], int] = False def __init__(self, parent=None, stateInfo=None): self.affectedTokens = [] @@ -336,7 +336,7 @@ def end(self): self.affectedTokens[0].tie = tie.Tie('start') else: self.affectedTokens[0].tie.type = 'continue' - if len(self.affectedTokens) > 1: # could be end. + if len(self.affectedTokens) > 1: # could be the end. self.affectedTokens[1].tie = tie.Tie('stop') @@ -391,7 +391,7 @@ class QuadrupletState(TupletState): class Modifier: ''' a modifier is something that changes the current - token, like setting the Id or Lyric. + token, like setting the `.id` or Lyric. ''' def __init__(self, modifierData, modifierString, parent): @@ -1437,6 +1437,8 @@ def testGetDefaultTokenMap(self) -> None: + f'{tokenType.__class__.__name__}.' ) ) + + # noinspection PyTypeChecker validTokenTypeCounts[tokenType] += 1 self.assertGreater( len(regex), diff --git a/music21/tree/fromStream.py b/music21/tree/fromStream.py index 52fd9c3497..06523272ed 100644 --- a/music21/tree/fromStream.py +++ b/music21/tree/fromStream.py @@ -14,7 +14,7 @@ Tools for creating timespans (fast, manipulable objects) from Streams ''' import unittest -from typing import Optional, Sequence, List, Type, Union, Tuple +from typing import Optional, Sequence, List, Type, Union, Tuple, Literal from music21.base import Music21Object from music21 import common @@ -147,11 +147,10 @@ def listOfTreesByClass( return outputTrees -# TODO(msc) -- after 3.7 is gone, make flatten string be the literal "semiFlat" def asTree( inputStream: 'music21.stream.Stream', *, - flatten: Union[str, bool] = False, + flatten: Union[Literal['semiFlat'], bool] = False, classList: Optional[Sequence[Type]] = None, useTimespans: bool = False, groupOffsets: bool = False diff --git a/music21/voiceLeading.py b/music21/voiceLeading.py index 833e238fd1..7627c9edc1 100644 --- a/music21/voiceLeading.py +++ b/music21/voiceLeading.py @@ -1232,10 +1232,6 @@ def opensIncorrectly(self) -> bool: c2 = chord.Chord([self.vIntervals[1].noteStart, self.vIntervals[1].noteEnd]) r1 = roman.identifyAsTonicOrDominant(c1, self.key) r2 = roman.identifyAsTonicOrDominant(c2, self.key) - # TODO in Py3.8+, remove when identifyAsTonicOrDominant returns Union[str | Literal[False]] - if r1 is True or r2 is True: - raise VoiceLeadingQuartetException( - 'identifyAsTonicOrDominant() returned True unexpectedly, please report a bug') openings = ['P1', 'P5', 'I', 'V'] return not ((self.vIntervals[0].simpleName in openings or self.vIntervals[1].simpleName in openings) diff --git a/setup.py b/setup.py index 4f4b33ca83..4863d665ac 100644 --- a/setup.py +++ b/setup.py @@ -66,7 +66,7 @@ setuptools.setup( name='music21', version=m21version, - python_requires='>=3.7', + python_requires='>=3.8', description=DESCRIPTION, long_description=DESCRIPTION_LONG, author='Michael Scott Cuthbert, the music21 project, others', From 7c922140f14a1909eaf354e7331daedc2d14d7f2 Mon Sep 17 00:00:00 2001 From: Myke Cuthbert Date: Tue, 19 Apr 2022 12:49:14 -1000 Subject: [PATCH 2/3] lint and flake --- music21/braille/segment.py | 5 +++-- music21/stream/iterator.py | 5 +---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/music21/braille/segment.py b/music21/braille/segment.py index 6eface8c63..c34550e36a 100644 --- a/music21/braille/segment.py +++ b/music21/braille/segment.py @@ -110,8 +110,9 @@ class Affinity(enum.IntEnum): layout.StaffLayout] class GroupingGlobals(TypedDict): - keySignature: Optional[key.KeySignature] - timeSignature: Optional[meter.TimeSignature] + keySignature: Optional[key.KeySignature] + timeSignature: Optional[meter.TimeSignature] + GROUPING_GLOBALS: GroupingGlobals = { 'keySignature': None, # will be key.KeySignature(0) on first call diff --git a/music21/stream/iterator.py b/music21/stream/iterator.py index acd1e1d2ab..f1c455cdda 100644 --- a/music21/stream/iterator.py +++ b/music21/stream/iterator.py @@ -16,7 +16,7 @@ ''' import copy from typing import (TypeVar, List, Union, Callable, Optional, Literal, - Dict, TypedDict, TYPE_CHECKING) + TypedDict) import unittest import warnings @@ -30,9 +30,6 @@ from music21.sites import SitesException -if TYPE_CHECKING: - import music21.stream - _SIter = TypeVar('_SIter') FilterType = Union[Callable, filters.StreamFilter] From cee811ea000b453d49753bdf172bc64bb04b23e9 Mon Sep 17 00:00:00 2001 From: Myke Cuthbert Date: Tue, 19 Apr 2022 13:01:55 -1000 Subject: [PATCH 3/3] coverage line --- music21/test/coverageM21.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/music21/test/coverageM21.py b/music21/test/coverageM21.py index 0ad03ec84f..3dadd6ad2c 100644 --- a/music21/test/coverageM21.py +++ b/music21/test/coverageM21.py @@ -34,8 +34,9 @@ def getCoverage(overrideVersion=False): - if overrideVersion or sys.version_info.minor == 7: - # run on Py 3.8 -- to get Py 3.9/3.10 timing... + # Note the .minor == 8 -- that makes it only run on 3.8 + # run on Py 3.8 -- to get Py 3.9/3.10 timing... + if overrideVersion or sys.version_info.minor == 8: try: import coverage # type: ignore cov = coverage.Coverage(omit=omit_modules)