Skip to content

Commit

Permalink
Converter/Corpus enhancements, Schumann (#1449)
Browse files Browse the repository at this point in the history
## Corpus/Converter

* Lots of typing and error detecting in Converter/Corpus

* speedups on searching, better flat warning

--------
## Schumann

* Remove default Schumann

Robert Schumann was a great composer

Clara Schumann was also a great composer

Don't assume that schumann means Robert. Rename to 'schumann_robert'. But allow a path so prior names still function.

* Fix buggy opus41no1 movement4.  Re-processed through Finale to eliminate buggy divisions.  Removed notated trills.
  • Loading branch information
mscuthbert authored Oct 6, 2022
1 parent bbd29fe commit e0b2ae2
Show file tree
Hide file tree
Showing 31 changed files with 444 additions and 27,658 deletions.
2 changes: 1 addition & 1 deletion music21/_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
'''
from __future__ import annotations

__version__ = '9.0.0a2'
__version__ = '9.0.0a3'


def get_version_tuple(vv):
Expand Down
15 changes: 12 additions & 3 deletions music21/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
<class 'music21.base.Music21Object'>
>>> music21.VERSION_STR
'9.0.0a2'
'9.0.0a3'
Alternatively, after doing a complete import, these classes are available
under the module "base":
Expand Down Expand Up @@ -68,6 +68,8 @@

if TYPE_CHECKING:
import fractions
from io import IOBase
import pathlib
from music21 import meter
from music21 import stream
from music21 import spanner
Expand Down Expand Up @@ -2776,7 +2778,12 @@ def _setPriority(self, value):
# -------------------------------------------------------------------------
# display and writing

def write(self, fmt=None, fp=None, **keywords): # pragma: no cover
def write(
self,
fmt: str | None = None,
fp: str | pathlib.Path | IOBase | None = None,
**keywords
) -> pathlib.Path: # pragma: no cover
'''
Write out a file of music notation (or an image, etc.) in a given format. If
fp is specified as a file path then the file will be placed there. If it is not
Expand All @@ -2802,13 +2809,15 @@ def write(self, fmt=None, fp=None, **keywords): # pragma: no cover

regularizedConverterFormat, unused_ext = common.findFormat(fmt)
if regularizedConverterFormat is None:
raise Music21ObjectException(f'cannot support showing in this format yet: {fmt}')
raise Music21ObjectException(f'cannot support output in this format yet: {fmt}')

formatSubs = fmt.split('.')
fmt = formatSubs[0]
subformats = formatSubs[1:]

scClass = common.findSubConverterForFormat(regularizedConverterFormat)
if scClass is None: # pragma: no cover
raise Music21ObjectException(f'cannot support output in this format yet: {fmt}')
formatWriter = scClass()
return formatWriter.write(self,
regularizedConverterFormat,
Expand Down
33 changes: 16 additions & 17 deletions music21/common/formats.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,14 @@
'VALID_AUTO_DOWNLOAD',
]

from functools import cache
import pathlib
import typing as t


if t.TYPE_CHECKING:
from music21.converter.subConverters import SubConverter


# used for checking preferences, and for setting environment variables
# TODO: only check top-level. Let subconverters check sub formats.
Expand All @@ -50,7 +57,7 @@
# ------------------------------------------------------------------------------


def findSubConverterForFormat(fmt):
def findSubConverterForFormat(fmt: str) -> type[SubConverter] | None:
'''
return a converter.subConverter.SubConverter subclass
for a given format -- this is a music21 format name,
Expand Down Expand Up @@ -78,6 +85,7 @@ def findSubConverterForFormat(fmt):
formats = sc.registerFormats
if fmt in formats:
return sc
return None


# @deprecated('May 2014', '[soonest possible]', 'Moved to converter')
Expand Down Expand Up @@ -166,22 +174,13 @@ def findFormat(fmt):

return fileFormat, firstOutput

# for key in sorted(list(fileExtensions)):
# if fmt.startswith('.'):
# fmt = fmt[1:] # strip .
# if fmt == key or fmt in fileExtensions[key]['input']:
# # add leading dot to extension on output
# return key, '.' + fileExtensions[key]['output']
# return None, None # if no match found

# @deprecated('May 2014', '[soonest possible]', 'Moved to converter')


def findInputExtension(fmt):
@cache
def findInputExtension(fmt: str) -> tuple[str, ...]:
'''
Will be fully deprecated when there's an exact equivalent in converter...
Given an input format or music21 format, find and return all possible
input extensions.
Expand All @@ -199,10 +198,10 @@ def findInputExtension(fmt):
>>> common.findInputExtension('.mxl')
('.xml', '.mxl', '.musicxml')
blah is neither
Blah is not a format
>>> common.findInputExtension('blah') is None
True
>>> common.findInputExtension('blah')
()
'''
from music21 import converter
fmt = fmt.lower().strip()
Expand All @@ -212,7 +211,7 @@ def findInputExtension(fmt):
sc = findSubConverterForFormat(fmt)
if sc is None:
# file extension
post = []
post: list[str] = []
for sc in converter.Converter().subconvertersList():
if fmt not in sc.registerInputExtensions:
continue
Expand All @@ -222,7 +221,7 @@ def findInputExtension(fmt):
post.append(ext)
if post:
return tuple(post)
return None
return tuple(post) # empty
else:
# music21 format
post = []
Expand Down
14 changes: 8 additions & 6 deletions music21/common/misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,13 @@
from __future__ import annotations

from collections.abc import Callable, Iterable
import copy
import os
import platform
import re
import sys
import textwrap
import time
import typing as t

__all__ = [
Expand All @@ -32,16 +37,13 @@
'cleanedFlatNotation',
]

import copy
import os
import sys
import textwrap
import time
if t.TYPE_CHECKING:
_T = t.TypeVar('_T')

# -----------------------------------------------------------------------------


def flattenList(originalList: list) -> list:
def flattenList(originalList: Iterable[Iterable[_T]]) -> list[_T]:
'''
Flatten a list of lists into a flat list
Expand Down
2 changes: 1 addition & 1 deletion music21/common/pathTools.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ def getCorpusContentDirs() -> list[str]:
'demos', 'essenFolksong', 'handel', 'haydn', 'joplin', 'josquin',
'leadSheet', 'luca', 'miscFolk', 'monteverdi', 'mozart', 'nottingham-dataset',
'oneills1850', 'palestrina',
'ryansMammoth', 'schoenberg', 'schubert', 'schumann', 'schumann_clara',
'ryansMammoth', 'schoenberg', 'schubert', 'schumann_clara', 'schumann_robert',
'theoryExercises', 'trecento', 'verdi', 'weber']
Make sure that all corpus data has a directoryInformation tag in
Expand Down
2 changes: 1 addition & 1 deletion music21/converter/qmConverter.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ def parseFile(self, filePath, number=None, **keywords):
with open(filePath, 'r', encoding='utf-8') as f:
self.parseData(f.read())

def write(self, obj, fmt, fp=None, subformats=None, **keywords): # pragma: no cover
def write(self, obj, fmt, fp=None, subformats=(), **keywords): # pragma: no cover
music = ''
if fp is None:
fp = environLocal.getTempFile('.qm')
Expand Down
Loading

0 comments on commit e0b2ae2

Please sign in to comment.