Example #1
0
    def testGetWorkList(self):
        self.assertEqual(len(corpus.getPaths('.md')) >= 38, True)
        workList = corpus.getWorkList('bach/artOfFugue_bwv1080', 1, '.zip')
        self.assertEqual(len(workList), 1)
        self.assertEqual(len(corpus.getWorkList('handel/hwv56', (1, 1), '.md')), 1)
        self.assertEqual(len(corpus.getWorkList('handel/hwv56', '1-01', '.md')), 1)
        self.assertEqual(len(corpus.getWorkList('bach/artOfFugue_bwv1080')), 21)
        self.assertEqual(len(corpus.getWorkList('bach/artOfFugue_bwv1080', 1)), 1)

        # there are two versions of this file
        self.assertEqual(len(corpus.getWorkList('beethoven/opus18no1', 1)), 2)

        # if specify movement
        for bwv in [
            'bwv846', 'bwv847', 'bwv848', 'bwv849', 'bwv850', 'bwv851',
            'bwv852', 'bwv853', 'bwv854', 'bwv855', 'bwv856', 'bwv857',
            'bwv858', 'bwv859', 'bwv860', 'bwv861', 'bwv862', 'bwv863',
            'bwv864', 'bwv865', 'bwv866', 'bwv867', 'bwv868', 'bwv869',
            'bwv870', 'bwv871', 'bwv872', 'bwv873', 'bwv874', 'bwv875',
            'bwv876', 'bwv877', 'bwv878', 'bwv879', 'bwv880', 'bwv881',
            'bwv882', 'bwv883', 'bwv884', 'bwv885', 'bwv886', 'bwv887',
            'bwv888', 'bwv889', 'bwv890', 'bwv891', 'bwv892', 'bwv893',
            ]:
            #print bwv
            self.assertEqual(len(corpus.getWorkList(bwv)), 2)
            self.assertEqual(len(corpus.getWorkList(bwv, 1)), 1)
            self.assertEqual(len(corpus.getWorkList(bwv, 2)), 1)
Example #2
0
def music21ModWSGICorpusURLApplication(environ, start_response):
    '''
    Application function in proper format for a MOD-WSGI Application:
    A server-mounted app that uses portions of the URL to parse and return musicxml of manipulated sections of corpus files. 
    Results can be returned either as a noteflight embed in the browser or downloaded as an xml file.
    
    '''
    status = '200 OK'

    pathInfo = environ['PATH_INFO'] # Contents of path after mount point of wsgi app but before question mark
    queryString = environ['QUERY_STRING'] # Contents of URL after question mark    
    returnType = queryString
    
    pathParts = pathInfo.split("/")
    
    error = False
    
    resultStr = ""
    
    if len(pathParts) > 1 and pathParts[1] in ['corpusParse','corpusReduce']:
        workList = corpus.getWorkList(pathParts[2])
        if len(workList) >1:
            resultStr = "Multiple choices for query "+pathParts[2]+". Please try one of the following\n"
            for p in workList:
                resultStr += path.splitext(path.basename(p))[0] + "\n"
            response_headers = [('Content-type', 'text/plain'),
            ('Content-Length', str(len(resultStr)))]
    
            start_response(status, response_headers)
        
            return [resultStr]
        elif len(workList) == 0:
            resultStr = "No results for for query "+pathParts[2]+"."
            response_headers = [('Content-type', 'text/plain'),
            ('Content-Length', str(len(resultStr)))]
    
            start_response(status, response_headers)
        
            return [resultStr]
        workName = workList[0]
        try:
            sc = corpus.parse(workName).measures(int(pathParts[3]),int(pathParts[4]))
            if pathParts[1] == 'corpusReduce':
                sc = reduction(sc)
            resultStr = sc.musicxml
            title = pathParts[2]+": Measures "+str(pathParts[3])+"-"+str(pathParts[4])
            filename = str(pathParts[2])+".m"+str(pathParts[3])+"-"+str(pathParts[4])+"-reduced.xml"
        except:
            try:
                sc = corpus.parse(pathParts[2]).measures(int(pathParts[3]),int(pathParts[3]))
                if pathParts[1] == 'corpusReduce':
                    sc = reduction(sc)
                resultStr = sc.musicxml
                title = pathParts[2]+": Measure "+str(pathParts[3])
                filename = str(pathParts[2])+".m"+str(pathParts[3])+"-reduced.xml"
            except:
                try:
                    sc = corpus.parse(pathParts[2])
                    if pathParts[1] == 'corpusReduce':
                        sc = reduction(sc)
                    resultStr = sc.musicxml 
                    title = pathParts[2]
                    filename = str(pathParts[2])+"-reduced.xml"
                except Exception as e:
                    resultStr = "Error parsing file "+str(e) + '\n\n'
                    error = True
    else:
        error = True

    if error:
        resultStr += "Try calling a url of the form:"
        resultStr += "\n  /music21/urlinterface/corpusParse/<WORKNAME> to download a musicxml file of the specified corpus file."
        resultStr += "\n\n  /music21/urlinterface/corpusParse/<WORKNAME>/<MEASURE_NUM> to download a musicxml file of the specified measure of a corpus file."
        resultStr += "\n\n  /music21/urlinterface/corpusParse/<WORKNAME>/<MEASURE_START>/<MEASURE_END> to download a musicxml file of the specified measures of a corpus file."
        resultStr += "\n\n  /music21/urlinterface/corpusReduce/<WORKNAME> to download an annotated, chordified reduction of the specified corpus file."
        resultStr += "\n\n  /music21/urlinterface/corpusReduce/<WORKNAME>/<MEASURE_NUM> to download an annotated, chordified reduction of the specified measure of a corpus file."
        resultStr += "\n\n  /music21/urlinterface/corpusReduce/<WORKNAME>/<MEASURE_START>/<MEASURE_END> to download an annotated, chordified reduction of the specified measures of a corpus file."
        resultStr += "\n\n\nSpecifying Return Format:"
        resultStr += "\n  The return format will default to a Noteflight embed that will load the resulting score."
        resultStr += "\n\n  Add ?xmltext to the end of the url to display the xmltext of the score as plain text"
        resultStr += "\n\n  Add ?xml to the end of the url to download the result as a .xml file"
        error = True
        
        response_headers = [('Content-type', 'text/plain'),
                ('Content-Length', str(len(resultStr)))]
    
        start_response(status, response_headers)
    
        return [resultStr]
    
    else:
        if returnType == "xml":
            response_headers = [('Content-type', 'application/vnd.recordare.musicxml+xml'),
                                ('Content-disposition','attachment; filename='+filename),
                                ('Content-Length', str(len(resultStr))),
                               ]
            start_response(status, response_headers)
            return [resultStr]
        
        elif returnType == "xmltext":
            
            response_headers = [('Content-type', 'text/plain'),
                                ('Content-Length', str(len(resultStr)))]
    
            start_response(status, response_headers)
        
            return [resultStr]
        
        else:
            templateStr = noteflightEmbedTemplate(resultStr,title)
            response_headers = [('Content-type', 'text/html'),
                                ('Content-Length', str(len(templateStr)))]
            start_response(status, response_headers)
        
            return [templateStr]
Example #3
0
    def parse(
        workName,
        movementNumber=None,
        number=None,
        fileExtensions=None,
        forceSource=False,
        ):
        '''
        The most important method call for corpus.

        Similar to the :meth:`~music21.converter.parse` method of converter
        (which takes in a filepath on the local hard drive), this method
        searches the corpus (including the virtual corpus) for a work fitting
        the workName description and returns a :class:`music21.stream.Stream`.

        If `movementNumber` is defined, and a movement is included in the
        corpus, that movement will be returned.

        If `number` is defined, and the work is a collection with multiple
        components, that work number will be returned.  For instance, some of
        our ABC documents contain dozens of folk songs within a single file.

        Advanced: if `forceSource` is True, the original file will always be
        loaded freshly and pickled (e.g., pre-parsed) files will be ignored.
        This should not be needed if the file has been changed, since the
        filetime of the file and the filetime of the pickled version are
        compared.  But it might be needed if the music21 parsing routine has
        changed.

        Example, get a chorale by Bach.  Note that the source type does not
        need to be specified, nor does the name Bach even (since it's the only
        piece with the title BWV 66.6)

        >>> from music21 import corpus
        >>> bachChorale = corpus.Corpus.parse('bwv66.6')
        >>> len(bachChorale.parts)
        4

        After parsing, the file path within the corpus is stored as
        ``.corpusFilePath``

        >>> bachChorale.corpusFilepath
        u'bach/bwv66.6.mxl'

        '''
        from music21 import corpus
        if workName in (None, ''):
            raise corpus.CorpusException(
                'a work name must be provided as an argument')
        if not common.isListLike(fileExtensions):
            fileExtensions = [fileExtensions]
        workList = corpus.getWorkList(
            workName, movementNumber, fileExtensions)
        if not workList:
            if common.isListLike(workName):
                workName = os.path.sep.join(workName)
            if workName.endswith(".xml"):
                # might be compressed MXL file
                newWorkName = os.path.splitext(workName)[0] + ".mxl"
                try:
                    return Corpus.parse(
                        newWorkName,
                        movementNumber,
                        number,
                        fileExtensions,
                        forceSource,
                        )
                except corpus.CorpusException:
                    # avoids having the name come back with .mxl instead of
                    # .xmlrle
                    raise corpus.CorpusException(
                        'Could not find an xml or mxl work that met this ' +
                        'criterion: {0}'.format(workName) + 
                        '. If you are searching for a file on disk, use "converter" instead of "corpus".')
            workList = corpus.getVirtualWorkList(
                workName,
                movementNumber,
                fileExtensions,
                )
        if len(workList) == 1:
            filePath = workList[0]
        elif not len(workList):
            raise corpus.CorpusException(
                'Could not find a work that met this criterion: {0};'.format(
                    workName) + 
                'if you are searching for a file on disk, use "converter" instead of "corpus".')
        else:
            filePath = workList[0]
        streamObject = converter.parse(
            filePath,
            forceSource=forceSource,
            number=number,
            )
        corpus._addCorpusFilepath(streamObject, filePath)
        return streamObject
Example #4
0
    def testGetWorkList(self):
        self.assertEqual(len(corpus.getPaths('.md')) >= 38, True)
        workList = corpus.getWorkList('bach/artOfFugue_bwv1080', 1, '.zip')
        self.assertEqual(len(workList), 1)
        self.assertEqual(
            len(corpus.getWorkList('handel/hwv56', (1, 1), '.md')), 1)
        self.assertEqual(
            len(corpus.getWorkList('handel/hwv56', '1-01', '.md')), 1)
        self.assertEqual(len(corpus.getWorkList('bach/artOfFugue_bwv1080')),
                         21)
        self.assertEqual(len(corpus.getWorkList('bach/artOfFugue_bwv1080', 1)),
                         1)

        # there are two versions of this file
        self.assertEqual(len(corpus.getWorkList('beethoven/opus18no1', 1)), 2)

        # if specify movement
        for bwv in [
                'bwv846',
                'bwv847',
                'bwv848',
                'bwv849',
                'bwv850',
                'bwv851',
                'bwv852',
                'bwv853',
                'bwv854',
                'bwv855',
                'bwv856',
                'bwv857',
                'bwv858',
                'bwv859',
                'bwv860',
                'bwv861',
                'bwv862',
                'bwv863',
                'bwv864',
                'bwv865',
                'bwv866',
                'bwv867',
                'bwv868',
                'bwv869',
                'bwv870',
                'bwv871',
                'bwv872',
                'bwv873',
                'bwv874',
                'bwv875',
                'bwv876',
                'bwv877',
                'bwv878',
                'bwv879',
                'bwv880',
                'bwv881',
                'bwv882',
                'bwv883',
                'bwv884',
                'bwv885',
                'bwv886',
                'bwv887',
                'bwv888',
                'bwv889',
                'bwv890',
                'bwv891',
                'bwv892',
                'bwv893',
        ]:
            #print bwv
            self.assertEqual(len(corpus.getWorkList(bwv)), 2)
            self.assertEqual(len(corpus.getWorkList(bwv, 1)), 1)
            self.assertEqual(len(corpus.getWorkList(bwv, 2)), 1)