예제 #1
0
    def parse(self, id):
        """Parse the input word transcriptions using the morphological parser with id=``id``.

        :param str id: the ``id`` value of the morphological parser that will be used.
        :Request body: JSON object of the form ``{'transcriptions': [t1, t2, ...]}``.
        :returns: if the morphological parser exists and foma is installed, a JSON object
            of the form ``{t1: p1, t2: p2, ...}`` where ``t1`` and ``t2`` are transcriptions
            of words from the request body and ``p1`` and ``p2`` are the most probable morphological
            parsers of t1 and t2.

        """
        parser = Session.query(MorphologicalParser).get(id)
        if not parser:
            response.status_int = 404
            return {'error': 'There is no morphological parser with id %s' % id}
        if not h.foma_installed():
            response.status_int = 400
            return {'error': 'Foma and flookup are not installed.'}
        try:
            inputs = json.loads(unicode(request.body, request.charset))
            schema = TranscriptionsSchema
            inputs = schema.to_python(inputs)
            inputs = [h.normalize(w) for w in inputs['transcriptions']]
            parses = parser.parse(inputs)
            # TODO: allow for a param which causes the candidates to be
            # returned as well as/instead of only the most probable parse
            # candidate.
            return dict((transcription, parse) for transcription, (parse, candidates) in
                        parses.iteritems())
        except h.JSONDecodeError:
            response.status_int = 400
            return h.JSONDecodeErrorResponse
        except Invalid, e:
            response.status_int = 400
            return {'errors': e.unpack_errors()}
예제 #2
0
    def applydown(self, id):
        """Apply-down (i.e., phonologize) the input in the request body using a phonology.

        :URL: ``PUT /phonologies/applydown/id`` (or ``PUT /phonologies/phonologize/id``)
        :param str id: the ``id`` value of the phonology that will be used.
        :Request body: JSON object of the form ``{'transcriptions': [t1, t2, ...]}``.
        :returns: if the phonology exists and foma is installed, a JSON object
            of the form ``{t1: [p1t1, p2t1, ...], ...}`` where ``t1`` is a
            transcription from the request body and ``p1t1``, ``p2t1``, etc. are
            phonologized outputs of ``t1``.

        """
        phonology = Session.query(Phonology).get(id)
        if phonology:
            if h.foma_installed():
                binary_path = phonology.get_file_path('binary')
                if os.path.isfile(binary_path):
                    try:
                        inputs = json.loads(unicode(request.body, request.charset))
                        inputs = MorphophonemicTranscriptionsSchema.to_python(inputs)
                        inputs = [h.normalize(i) for i in inputs['transcriptions']]
                        return phonology.applydown(inputs)
                    except h.JSONDecodeError:
                        response.status_int = 400
                        return h.JSONDecodeErrorResponse
                    except Invalid, e:
                        response.status_int = 400
                        return {'errors': e.unpack_errors()}
                else:
                    response.status_int = 400
                    return {'error': 'Phonology %d has not been compiled yet.' % phonology.id}
            else:
                response.status_int = 400
                return {'error': 'Foma and flookup are not installed.'}
예제 #3
0
    def compile(self, id):
        """Compile the script of a phonology as a foma FST.

        :URL: ``PUT /phonologies/compile/id``
        :param str id: the ``id`` value of the phonology whose script will be compiled.
        :returns: if the phonology exists and foma is installed, the phonology
            model is returned;  ``GET /phonologies/id`` must be polled to
            determine when and how the compilation task has terminated.

        .. note::

            The script is compiled asynchronously in a worker thread.  See 
            :mod:`onlinelinguisticdatabase.lib.foma_worker`.

        """
        phonology = Session.query(Phonology).get(id)
        if phonology:
            if h.foma_installed():
                foma_worker_q.put({
                    'id': h.generate_salt(),
                    'func': 'compile_phonology',
                    'args': {
                        'phonology_id': phonology.id,
                        'user_id': session['user'].id,
                        'timeout': h.phonology_compile_timeout
                    }
                })
                return phonology
            else:
                response.status_int = 400
                return {'error': 'Foma and flookup are not installed.'}
        else:
            response.status_int = 404
            return {'error': 'There is no phonology with id %s' % id}
예제 #4
0
    def apply(self, id, direction):
        """Call foma apply in the direction of ``direction`` on the input in the request body using a morphology.

        :param str id: the ``id`` value of the morphology that will be used.
        :param str direction: the direction of foma application.
        :Request body: JSON object of the form ``{'transcriptions': [t1, t2, ...]}``.
        :returns: if the morphology exists and foma is installed, a JSON object
            of the form ``{t1: [p1t1, p2t1, ...], ...}`` where ``t1`` is a
            transcription from the request body and ``p1t1``, ``p2t1``, etc. are
            outputs of ``t1`` after apply up/down.

        """
        morphology = Session.query(Morphology).get(id)
        if morphology:
            if h.foma_installed():
                morphology_binary_path = morphology.get_file_path('binary')
                if os.path.isfile(morphology_binary_path):
                    try:
                        inputs = json.loads(unicode(request.body, request.charset))
                        inputs = MorphemeSequencesSchema.to_python(inputs)
                        inputs = [h.normalize(i) for i in inputs['morpheme_sequences']]
                        return morphology.apply(direction, inputs)
                    except h.JSONDecodeError:
                        response.status_int = 400
                        return h.JSONDecodeErrorResponse
                    except Invalid, e:
                        response.status_int = 400
                        return {'errors': e.unpack_errors()}
                else:
                    response.status_int = 400
                    return {'error': 'Morphology %d has not been compiled yet.' % morphology.id}
            else:
                response.status_int = 400
                return {'error': 'Foma and flookup are not installed.'}
예제 #5
0
    def servecompiled(self, id):
        """Serve the compiled foma script of the morphophonology FST of the morphological parser.

        :URL: ``PUT /morphologicalparsers/servecompiled/id``
        :param str id: the ``id`` value of a morphological parser.
        :returns: a stream of bytes -- the compiled morphological parser script.  

        """
        parser = Session.query(MorphologicalParser).get(id)
        if parser:
            if h.foma_installed():
                binary_path = parser.get_file_path('binary')
                if os.path.isfile(binary_path):
                    return forward(FileApp(binary_path))
                else:
                    response.status_int = 400
                    return json.dumps({
                        'error':
                        'The morphophonology foma script of '
                        'MorphologicalParser %d has not been compiled yet.' %
                        parser.id
                    })
            else:
                response.status_int = 400
                return json.dumps(
                    {'error': 'Foma and flookup are not installed.'})
        else:
            response.status_int = 404
            return json.dumps(
                {'error': 'There is no morphological parser with id %s' % id})
예제 #6
0
    def parse(self, id):
        """Parse the input word transcriptions using the morphological parser with id=``id``.

        :param str id: the ``id`` value of the morphological parser that will be used.
        :Request body: JSON object of the form ``{'transcriptions': [t1, t2, ...]}``.
        :returns: if the morphological parser exists and foma is installed, a JSON object
            of the form ``{t1: p1, t2: p2, ...}`` where ``t1`` and ``t2`` are transcriptions
            of words from the request body and ``p1`` and ``p2`` are the most probable morphological
            parsers of t1 and t2.

        """
        parser = Session.query(MorphologicalParser).get(id)
        if not parser:
            response.status_int = 404
            return {'error': 'There is no morphological parser with id %s' % id}
        if not h.foma_installed():
            response.status_int = 400
            return {'error': 'Foma and flookup are not installed.'}
        try:
            inputs = json.loads(unicode(request.body, request.charset))
            schema = TranscriptionsSchema
            inputs = schema.to_python(inputs)
            return parser.parse(inputs['transcriptions'])
        except h.JSONDecodeError:
            response.status_int = 400
            return h.JSONDecodeErrorResponse
        except Invalid, e:
            response.status_int = 400
            return {'errors': e.unpack_errors()}
예제 #7
0
def generate_and_compile_morphological_parser(morphological_parser_id, compile_=True):
    morphological_parser = Session.query(MorphologicalParser).get(morphological_parser_id)
    if not morphological_parser:
        response.status_int = 404
        return {'error': 'There is no morphological parser with id %s' % id}
    if compile_ and not h.foma_installed():
        response.status_int = 400
        return {'error': 'Foma and flookup are not installed.'}
    foma_worker_q.put({
        'id': h.generate_salt(),
        'func': 'generate_and_compile_parser',
        'args': {
            'morphological_parser_id': morphological_parser.id,
            'compile': compile_,
            'user_id': session['user'].id,
            'timeout': h.morphological_parser_compile_timeout
        }
    })
    return morphological_parser
예제 #8
0
    def apply(self, id, direction):
        """Call foma apply in the direction of ``direction`` on the input in the request body using a morphological parser.

        :param str id: the ``id`` value of the morphological parser that will be used.
        :param str direction: the direction of foma application.
        :Request body: JSON object of the form ``{'transcriptions': [t1, t2, ...]}``.
        :returns: if the morphological parser exists and foma is installed, a JSON object
            of the form ``{t1: [p1t1, p2t1, ...], ...}`` where ``t1`` is a
            transcription from the request body and ``p1t1``, ``p2t1``, etc. are
            outputs of ``t1`` after apply up/down.

        """
        parser = Session.query(MorphologicalParser).get(id)
        if parser:
            if h.foma_installed():
                binary_path = parser.get_file_path('binary')
                if os.path.isfile(binary_path):
                    try:
                        inputs = json.loads(
                            unicode(request.body, request.charset))
                        schema, key = {'up': (TranscriptionsSchema, 'transcriptions'),
                                       'down': (MorphemeSequencesSchema, 'morpheme_sequences')}.\
                                        get(direction, (MorphemeSequencesSchema, 'morpheme_sequences'))
                        inputs = schema.to_python(inputs)
                        return parser.apply(direction, inputs[key])
                    except h.JSONDecodeError:
                        response.status_int = 400
                        return h.JSONDecodeErrorResponse
                    except Invalid, e:
                        response.status_int = 400
                        return {'errors': e.unpack_errors()}
                else:
                    response.status_int = 400
                    return json.dumps({
                        'error':
                        'The morphophonology foma script of '
                        'MorphologicalParser %d has not been compiled yet.' %
                        parser.id
                    })
            else:
                response.status_int = 400
                return {'error': 'Foma and flookup are not installed.'}
예제 #9
0
def generate_and_compile_morphological_parser(morphological_parser_id,
                                              compile_=True):
    morphological_parser = Session.query(MorphologicalParser).get(
        morphological_parser_id)
    if not morphological_parser:
        response.status_int = 404
        return {'error': 'There is no morphological parser with id %s' % id}
    if compile_ and not h.foma_installed():
        response.status_int = 400
        return {'error': 'Foma and flookup are not installed.'}
    foma_worker_q.put({
        'id': h.generate_salt(),
        'func': 'generate_and_compile_parser',
        'args': {
            'morphological_parser_id': morphological_parser.id,
            'compile': compile_,
            'user_id': session['user'].id,
            'timeout': h.morphological_parser_compile_timeout
        }
    })
    return morphological_parser
예제 #10
0
    def parse(self, id):
        """Parse the input word transcriptions using the morphological parser with id=``id``.

        :param str id: the ``id`` value of the morphological parser that will be used.
        :Request body: JSON object of the form ``{'transcriptions': [t1, t2, ...]}``.
        :returns: if the morphological parser exists and foma is installed, a JSON object
            of the form ``{t1: p1, t2: p2, ...}`` where ``t1`` and ``t2`` are transcriptions
            of words from the request body and ``p1`` and ``p2`` are the most probable morphological
            parsers of t1 and t2.

        """
        parser = Session.query(MorphologicalParser).get(id)
        if not parser:
            response.status_int = 404
            return {
                'error': 'There is no morphological parser with id %s' % id
            }
        if not h.foma_installed():
            response.status_int = 400
            return {'error': 'Foma and flookup are not installed.'}
        try:
            inputs = json.loads(unicode(request.body, request.charset))
            schema = TranscriptionsSchema
            inputs = schema.to_python(inputs)
            inputs = [h.normalize(w) for w in inputs['transcriptions']]
            parses = parser.parse(inputs)
            # TODO: allow for a param which causes the candidates to be
            # returned as well as/instead of only the most probable parse
            # candidate.
            return dict(
                (transcription, parse)
                for transcription, (parse, candidates) in parses.iteritems())
        except h.JSONDecodeError:
            response.status_int = 400
            return h.JSONDecodeErrorResponse
        except Invalid, e:
            response.status_int = 400
            return {'errors': e.unpack_errors()}
예제 #11
0
    def servecompiled(self, id):
        """Serve the compiled foma script of the phonology.

        :URL: ``PUT /phonologies/servecompiled/id``
        :param str id: the ``id`` value of a phonology.
        :returns: a stream of bytes -- the compiled phonology script.  

        """
        phonology = Session.query(Phonology).get(id)
        if phonology:
            if h.foma_installed():
                compiled_path = phonology.get_file_path('binary')
                if os.path.isfile(compiled_path):
                    return forward(FileApp(compiled_path))
                else:
                    response.status_int = 400
                    return json.dumps({'error': 'Phonology %d has not been compiled yet.' % phonology.id})
            else:
                response.status_int = 400
                return json.dumps({'error': 'Foma and flookup are not installed.'})
        else:
            response.status_int = 404
            return json.dumps({'error': 'There is no phonology with id %s' % id})
예제 #12
0
    def runtests(self, id):
        """Run the tests defined in the phonology's script against the phonology.

        A line in a phonology's script that begins with "#test" signifies a
        test.  After "#test" there should be a string of characters followed by
        "->" followed by another string of characters.  The first string is the
        underlying representation and the second is the anticipated surface
        representation.  Requests to ``GET /phonologies/runtests/id`` will cause
        the OLD to run a phonology script against its tests and return a
        dictionary detailing the expected and actual outputs of each input in
        the transcription.

        :URL: ``GET /phonologies/runtests/id``
        :param str id: the ``id`` value of the phonology that will be tested.
        :returns: if the phonology exists and foma is installed, a JSON object
            representing the results of the test.

        """
        phonology = Session.query(Phonology).get(id)
        if phonology:
            if h.foma_installed():
                try:
                    test_results = phonology.run_tests()
                    if test_results:
                        return test_results
                    else:
                        response.status_int = 400
                        return {'error': 'The script of phonology %d contains no tests.' % phonology.id}
                except AttributeError:
                    response.status_int = 400
                    return {'error': 'Phonology %d has not been compiled yet.' % phonology.id}
            else:
                response.status_int = 400
                return {'error': 'Foma and flookup are not installed.'}
        else:
            response.status_int = 404
            return {'error': 'There is no phonology with id %s' % id}
예제 #13
0
    def apply(self, id, direction):
        """Call foma apply in the direction of ``direction`` on the input in the request body using a morphological parser.

        :param str id: the ``id`` value of the morphological parser that will be used.
        :param str direction: the direction of foma application.
        :Request body: JSON object of the form ``{'transcriptions': [t1, t2, ...]}``.
        :returns: if the morphological parser exists and foma is installed, a JSON object
            of the form ``{t1: [p1t1, p2t1, ...], ...}`` where ``t1`` is a
            transcription from the request body and ``p1t1``, ``p2t1``, etc. are
            outputs of ``t1`` after apply up/down.

        """
        parser = Session.query(MorphologicalParser).get(id)
        if parser:
            if h.foma_installed():
                binary_path = parser.get_file_path('binary')
                if os.path.isfile(binary_path):
                    try:
                        inputs = json.loads(unicode(request.body, request.charset))
                        schema, key = {'up': (TranscriptionsSchema, 'transcriptions'),
                                       'down': (MorphemeSequencesSchema, 'morpheme_sequences')}.\
                                        get(direction, (MorphemeSequencesSchema, 'morpheme_sequences'))
                        inputs = schema.to_python(inputs)
                        return parser.apply(direction, inputs[key])
                    except h.JSONDecodeError:
                        response.status_int = 400
                        return h.JSONDecodeErrorResponse
                    except Invalid, e:
                        response.status_int = 400
                        return {'errors': e.unpack_errors()}
                else:
                    response.status_int = 400
                    return json.dumps({'error': 'The morphophonology foma script of '
                        'MorphologicalParser %d has not been compiled yet.' % parser.id})
            else:
                response.status_int = 400
                return {'error': 'Foma and flookup are not installed.'}
예제 #14
0
    def servecompiled(self, id):
        """Serve the compiled foma script of the morphophonology FST of the morphological parser.

        :URL: ``PUT /morphologicalparsers/servecompiled/id``
        :param str id: the ``id`` value of a morphological parser.
        :returns: a stream of bytes -- the compiled morphological parser script.  

        """
        parser = Session.query(MorphologicalParser).get(id)
        if parser:
            if h.foma_installed():
                binary_path = parser.get_file_path('binary')
                if os.path.isfile(binary_path):
                    return forward(FileApp(binary_path))
                else:
                    response.status_int = 400
                    return json.dumps({'error': 'The morphophonology foma script of '
                        'MorphologicalParser %d has not been compiled yet.' % parser.id})
            else:
                response.status_int = 400
                return json.dumps({'error': 'Foma and flookup are not installed.'})
        else:
            response.status_int = 404
            return json.dumps({'error': 'There is no morphological parser with id %s' % id})