コード例 #1
0
ファイル: rememberedforms.py プロジェクト: jrwdunham/old
    def show(self, id):
        """Return a user's remembered forms.
        
        :URL: ``GET /rememberedforms/id`` with optional query string parameters
            for ordering and pagination.
        :param str id: the ``id`` value of a user model.
        :returns: a list form models.

        .. note::

            Any authenticated user is authorized to access this resource.
            Restricted forms are filtered from the array on a per-user basis.

        .. note::

           See :func:`utils.add_order_by` and :func:`utils.add_pagination` for the
           query string parameters that effect ordering and pagination.

        """
        user = Session.query(User).get(id)
        if user:
            try:
                query = h.eagerload_form(Session.query(Form))\
                            .filter(Form.memorizers.contains(user))
                query = h.add_order_by(query, dict(request.GET), self.query_builder)
                query = h.filter_restricted_models('Form', query)
                return h.add_pagination(query, dict(request.GET))
            except Invalid, e:
                response.status_int = 400
                return {'errors': e.unpack_errors()}
コード例 #2
0
ファイル: users.py プロジェクト: jrwdunham/old
    def update(self, id):
        """Update a user and return it.
        
        :URL: ``PUT /users/id``
        :Request body: JSON object representing the user with updated attribute values.
        :param str id: the ``id`` value of the user to be updated.
        :returns: the updated user model.

        """
        user = Session.query(User).get(int(id))
        if user:
            try:
                schema = UserSchema()
                values = json.loads(unicode(request.body, request.charset))
                state = h.get_state_object(values)
                state.user_to_update = user.get_full_dict()
                current_user = Session.query(User).get(session['user'].id)
                state.user = current_user.get_full_dict()
                data = schema.to_python(values, state)
                user = update_user(user, data)
                # user will be False if there are no changes (cf. update_user).
                if user:
                    Session.add(user)
                    Session.commit()
                    return user.get_full_dict()
                else:
                    response.status_int = 400
                    return {'error':
                        u'The update request failed because the submitted data were not new.'}
            except h.JSONDecodeError:
                response.status_int = 400
                return h.JSONDecodeErrorResponse
            except Invalid, e:
                response.status_int = 400
                return {'errors': e.unpack_errors()}
コード例 #3
0
    def show(self, id):
        """Return a user's remembered forms.
        
        :URL: ``GET /rememberedforms/id`` with optional query string parameters
            for ordering and pagination.
        :param str id: the ``id`` value of a user model.
        :returns: a list form models.

        .. note::

            Any authenticated user is authorized to access this resource.
            Restricted forms are filtered from the array on a per-user basis.

        .. note::

           See :func:`utils.add_order_by` and :func:`utils.add_pagination` for the
           query string parameters that effect ordering and pagination.

        """
        user = Session.query(User).get(id)
        if user:
            try:
                query = h.eagerload_form(Session.query(Form))\
                            .filter(Form.memorizers.contains(user))
                query = h.add_order_by(query, dict(request.GET),
                                       self.query_builder)
                query = h.filter_restricted_models('Form', query)
                return h.add_pagination(query, dict(request.GET))
            except Invalid, e:
                response.status_int = 400
                return {'errors': e.unpack_errors()}
コード例 #4
0
    def test_create(self):
        """Tests that POST /elicitationmethods creates a new elicitation method
        or returns an appropriate error if the input is invalid.
        """

        original_EM_count = Session.query(ElicitationMethod).count()

        # Create a valid one
        params = json.dumps({'name': u'em', 'description': u'Described.'})
        response = self.app.post(url('elicitationmethods'), params, self.json_headers, self.extra_environ_admin)
        resp = json.loads(response.body)
        new_EM_count = Session.query(ElicitationMethod).count()
        assert new_EM_count == original_EM_count + 1
        assert resp['name'] == u'em'
        assert resp['description'] == u'Described.'
        assert response.content_type == 'application/json'

        # Invalid because name is not unique
        params = json.dumps({'name': u'em', 'description': u'Described.'})
        response = self.app.post(url('elicitationmethods'), params, self.json_headers, self.extra_environ_admin, status=400)
        resp = json.loads(response.body)
        assert resp['errors']['name'] == u'The submitted value for ElicitationMethod.name is not unique.'
        assert response.content_type == 'application/json'

        # Invalid because name is empty
        params = json.dumps({'name': u'', 'description': u'Described.'})
        response = self.app.post(url('elicitationmethods'), params, self.json_headers, self.extra_environ_admin, status=400)
        resp = json.loads(response.body)
        assert resp['errors']['name'] == u'Please enter a value'

        # Invalid because name is too long
        params = json.dumps({'name': u'name' * 400, 'description': u'Described.'})
        response = self.app.post(url('elicitationmethods'), params, self.json_headers, self.extra_environ_admin, status=400)
        resp = json.loads(response.body)
        assert resp['errors']['name'] == u'Enter a value not more than 255 characters long'
コード例 #5
0
    def test_update(self):
        """Tests that PUT /speakers/id updates the speaker with id=id."""

        # Create a speaker to update.
        params = self.speaker_create_params.copy()
        params.update({
            'first_name': u'first_name',
            'last_name': u'last_name',
            'page_content': u'page_content',
            'dialect': u'dialect'
        })
        params = json.dumps(params)
        response = self.app.post(url('speakers'), params, self.json_headers,
                                 self.extra_environ_admin)
        resp = json.loads(response.body)
        speaker_count = Session.query(Speaker).count()
        speaker_id = resp['id']
        original_datetime_modified = resp['datetime_modified']

        # Update the speaker
        sleep(
            1
        )  # sleep for a second to ensure that MySQL registers a different datetime_modified for the update
        params = self.speaker_create_params.copy()
        params.update({
            'first_name': u'first_name',
            'last_name': u'last_name',
            'page_content': u'page_content',
            'dialect': u'updated dialect.'
        })
        params = json.dumps(params)
        response = self.app.put(url('speaker', id=speaker_id), params,
                                self.json_headers, self.extra_environ_admin)
        resp = json.loads(response.body)
        datetime_modified = resp['datetime_modified']
        new_speaker_count = Session.query(Speaker).count()
        assert speaker_count == new_speaker_count
        assert datetime_modified != original_datetime_modified
        assert response.content_type == 'application/json'

        # Attempt an update with no new input and expect to fail
        sleep(
            1
        )  # sleep for a second to ensure that MySQL could register a different datetime_modified for the update
        response = self.app.put(url('speaker', id=speaker_id),
                                params,
                                self.json_headers,
                                self.extra_environ_admin,
                                status=400)
        resp = json.loads(response.body)
        speaker_count = new_speaker_count
        new_speaker_count = Session.query(Speaker).count()
        our_speaker_datetime_modified = Session.query(Speaker).get(
            speaker_id).datetime_modified
        assert our_speaker_datetime_modified.isoformat() == datetime_modified
        assert speaker_count == new_speaker_count
        assert resp[
            'error'] == u'The update request failed because the submitted data were not new.'
        assert response.content_type == 'application/json'
コード例 #6
0
ファイル: test_pages.py プロジェクト: dativebase/old
    def test_update(self):
        """Tests that PUT /pages/id updates the page with id=id."""

        # Create a page to update.
        params = self.page_create_params.copy()
        params.update({
            'name': u'page',
            'markup_language': u'Markdown',
            'content': self.md_contents
        })
        params = json.dumps(params)
        response = self.app.post(url('pages'), params, self.json_headers,
                                 self.extra_environ_admin)
        resp = json.loads(response.body)
        page_count = Session.query(Page).count()
        page_id = resp['id']
        original_datetime_modified = resp['datetime_modified']

        # Update the page
        sleep(
            1
        )  # sleep for a second to ensure that MySQL registers a different datetime_modified for the update
        params = self.page_create_params.copy()
        params.update({
            'name': u'Awesome Page',
            'markup_language': u'Markdown',
            'content': self.md_contents
        })
        params = json.dumps(params)
        response = self.app.put(url('page', id=page_id), params,
                                self.json_headers, self.extra_environ_admin)
        resp = json.loads(response.body)
        datetime_modified = resp['datetime_modified']
        new_page_count = Session.query(Page).count()
        assert page_count == new_page_count
        assert datetime_modified != original_datetime_modified
        assert resp['name'] == u'Awesome Page'
        assert response.content_type == 'application/json'

        # Attempt an update with no new input and expect to fail
        sleep(
            1
        )  # sleep for a second to ensure that MySQL could register a different datetime_modified for the update
        response = self.app.put(url('page', id=page_id),
                                params,
                                self.json_headers,
                                self.extra_environ_admin,
                                status=400)
        resp = json.loads(response.body)
        page_count = new_page_count
        new_page_count = Session.query(Page).count()
        our_page_datetime_modified = Session.query(Page).get(
            page_id).datetime_modified
        assert our_page_datetime_modified.isoformat() == datetime_modified
        assert page_count == new_page_count
        assert resp[
            'error'] == u'The update request failed because the submitted data were not new.'
        assert response.content_type == 'application/json'
コード例 #7
0
ファイル: test_tags.py プロジェクト: FieldDB/old
    def test_delete(self):
        """Tests that DELETE /tags/id deletes the tag with id=id."""

        # Create a tag to delete.
        params = json.dumps({'name': u'name', 'description': u'description'})
        response = self.app.post(url('tags'), params, self.json_headers,
                                 self.extra_environ_admin)
        resp = json.loads(response.body)
        tag_count = Session.query(Tag).count()
        tag_id = resp['id']

        # Now delete the tag
        response = self.app.delete(url('tag', id=tag_id), headers=self.json_headers,
            extra_environ=self.extra_environ_admin)
        resp = json.loads(response.body)
        new_tag_count = Session.query(Tag).count()
        assert new_tag_count == tag_count - 1
        assert resp['id'] == tag_id
        assert response.content_type == 'application/json'

        # Trying to get the deleted tag from the db should return None
        deleted_tag = Session.query(Tag).get(tag_id)
        assert deleted_tag == None

        # Delete with an invalid id
        id = 9999999999999
        response = self.app.delete(url('tag', id=id),
            headers=self.json_headers, extra_environ=self.extra_environ_admin,
            status=404)
        assert u'There is no tag with id %s' % id in json.loads(response.body)['error']
        assert response.content_type == 'application/json'

        # Delete without an id
        response = self.app.delete(url('tag', id=''), status=404,
            headers=self.json_headers, extra_environ=self.extra_environ_admin)
        assert json.loads(response.body)['error'] == 'The resource could not be found.'
        assert response.content_type == 'application/json'

        # Create a form, tag it, delete the tag and show that the form no longer
        # has the tag.
        tag = model.Tag()
        tag.name = u'tag'
        form = model.Form()
        form.transcription = u'test'
        form.tags.append(tag)
        Session.add_all([form, tag])
        Session.commit()
        form_id = form.id
        tag_id = tag.id
        response = self.app.delete(url('tag', id=tag_id),
            headers=self.json_headers, extra_environ=self.extra_environ_admin)
        deleted_tag = Session.query(Tag).get(tag_id)
        form = Session.query(model.Form).get(form_id)
        assert response.content_type == 'application/json'
        assert deleted_tag == None
        assert form.tags == []
コード例 #8
0
ファイル: test_tags.py プロジェクト: dativebase/old
    def test_create(self):
        """Tests that POST /tags creates a new tag
        or returns an appropriate error if the input is invalid.
        """

        original_tag_count = Session.query(Tag).count()

        # Create a valid one
        params = json.dumps({'name': u'tag', 'description': u'Described.'})
        response = self.app.post(url('tags'), params, self.json_headers,
                                 self.extra_environ_admin)
        resp = json.loads(response.body)
        new_tag_count = Session.query(Tag).count()
        assert new_tag_count == original_tag_count + 1
        assert resp['name'] == u'tag'
        assert resp['description'] == u'Described.'
        assert response.content_type == 'application/json'

        # Invalid because name is not unique
        params = json.dumps({'name': u'tag', 'description': u'Described.'})
        response = self.app.post(url('tags'),
                                 params,
                                 self.json_headers,
                                 self.extra_environ_admin,
                                 status=400)
        resp = json.loads(response.body)
        assert resp['errors'][
            'name'] == u'The submitted value for Tag.name is not unique.'

        # Invalid because name is empty
        params = json.dumps({'name': u'', 'description': u'Described.'})
        response = self.app.post(url('tags'),
                                 params,
                                 self.json_headers,
                                 self.extra_environ_admin,
                                 status=400)
        resp = json.loads(response.body)
        assert resp['errors']['name'] == u'Please enter a value'
        assert response.content_type == 'application/json'

        # Invalid because name is too long
        params = json.dumps({
            'name': u'name' * 400,
            'description': u'Described.'
        })
        response = self.app.post(url('tags'),
                                 params,
                                 self.json_headers,
                                 self.extra_environ_admin,
                                 status=400)
        resp = json.loads(response.body)
        assert resp['errors'][
            'name'] == u'Enter a value not more than 255 characters long'
        assert response.content_type == 'application/json'
コード例 #9
0
    def test_delete(self):
        """Tests that DELETE /formsearches/id deletes the form search with id=id."""

        # Create a form search to delete.
        query = {'filter': ['Form', 'transcription', 'regex', u'[a-g]{3,}']}
        params = self.form_search_create_params.copy()
        params.update({
            'name': u'form search',
            'description': u'This one\'s worth saving!',
            'search': query
        })
        params = json.dumps(params)
        response = self.app.post(url('formsearches'), params,
                                 self.json_headers, self.extra_environ_admin)
        resp = json.loads(response.body)
        form_search_count = Session.query(FormSearch).count()
        form_search_id = resp['id']
        assert resp['name'] == u'form search'
        assert resp['description'] == u"This one's worth saving!"
        assert resp['search'] == query

        # Now delete the form_search
        response = self.app.delete(url('formsearch', id=form_search_id),
                                   headers=self.json_headers,
                                   extra_environ=self.extra_environ_admin)
        resp = json.loads(response.body)
        new_form_search_count = Session.query(FormSearch).count()
        assert new_form_search_count == form_search_count - 1
        assert resp['id'] == form_search_id
        assert response.content_type == 'application/json'

        # Trying to get the deleted form_search from the db should return None
        deleted_form_search = Session.query(FormSearch).get(form_search_id)
        assert deleted_form_search == None

        # Delete with an invalid id
        id = 9999999999999
        response = self.app.delete(url('formsearch', id=id),
                                   headers=self.json_headers,
                                   extra_environ=self.extra_environ_admin,
                                   status=404)
        assert u'There is no form search with id %s' % id in json.loads(
            response.body)['error']
        assert response.content_type == 'application/json'

        # Delete without an id
        response = self.app.delete(url('formsearch', id=''),
                                   status=404,
                                   headers=self.json_headers,
                                   extra_environ=self.extra_environ_admin)
        assert json.loads(
            response.body)['error'] == 'The resource could not be found.'
コード例 #10
0
ファイル: login.py プロジェクト: dativebase/old
    def authenticate(self):
        """Session-based authentication.

        :URL: ``POST /login/authenticate``
        :request body: A JSON object with ``"username"`` and ``"password"``
            string values
        :returns: ``{"authenticated": True}`` on success, an error dictionary on
            failure.

        """
        try:
            schema = LoginSchema()
            values = json.loads(unicode(request.body, request.charset))
            result = schema.to_python(values)
            username = result['username']
            user_from_username = Session.query(User).filter(
                User.username == username).first()
            if user_from_username:
                salt = user_from_username.salt
                password = unicode(
                    h.encrypt_password(result['password'], str(salt)))
                user = Session.query(User).filter(
                    User.username == username).filter(
                        User.password == password).first()
                if user:
                    session['user'] = user
                    session.save()
                    home_page = Session.query(Page).filter(
                        Page.name == u'home').first()
                    return {
                        'authenticated': True,
                        'user': user,
                        'homepage': home_page
                    }
                else:
                    response.status_int = 401
                    return {
                        'error':
                        u'The username and password provided are not valid.'
                    }
            else:
                response.status_int = 401
                return {
                    'error':
                    u'The username and password provided are not valid.'
                }
        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 test_delete(self):
        """Tests that DELETE /speakers/id deletes the speaker with id=id."""

        # Create a speaker to delete.
        params = self.speaker_create_params.copy()
        params.update({
            'first_name': u'first_name',
            'last_name': u'last_name',
            'page_content': u'page_content',
            'dialect': u'dialect'
        })
        params = json.dumps(params)
        response = self.app.post(url('speakers'), params, self.json_headers,
                                 self.extra_environ_admin)
        resp = json.loads(response.body)
        speaker_count = Session.query(Speaker).count()
        speaker_id = resp['id']

        # Now delete the speaker
        response = self.app.delete(url('speaker', id=speaker_id),
                                   headers=self.json_headers,
                                   extra_environ=self.extra_environ_admin)
        resp = json.loads(response.body)
        new_speaker_count = Session.query(Speaker).count()
        assert new_speaker_count == speaker_count - 1
        assert resp['id'] == speaker_id
        assert response.content_type == 'application/json'

        # Trying to get the deleted speaker from the db should return None
        deleted_speaker = Session.query(Speaker).get(speaker_id)
        assert deleted_speaker == None
        assert response.content_type == 'application/json'

        # Delete with an invalid id
        id = 9999999999999
        response = self.app.delete(url('speaker', id=id),
                                   headers=self.json_headers,
                                   extra_environ=self.extra_environ_admin,
                                   status=404)
        assert u'There is no speaker with id %s' % id in json.loads(
            response.body)['error']
        assert response.content_type == 'application/json'

        # Delete without an id
        response = self.app.delete(url('speaker', id=''),
                                   status=404,
                                   headers=self.json_headers,
                                   extra_environ=self.extra_environ_admin)
        assert json.loads(
            response.body)['error'] == 'The resource could not be found.'
        assert response.content_type == 'application/json'
コード例 #12
0
ファイル: test_pages.py プロジェクト: jrwdunham/old
    def test_create(self):
        """Tests that POST /pages creates a new page
        or returns an appropriate error if the input is invalid.
        """

        original_page_count = Session.query(Page).count()

        # Create a valid one
        params = self.page_create_params.copy()
        params.update({
            'name': u'page',
            'markup_language': u'Markdown',
            'content': self.md_contents
        })
        params = json.dumps(params)
        response = self.app.post(url('pages'), params, self.json_headers, self.extra_environ_admin)
        resp = json.loads(response.body)
        new_page_count = Session.query(Page).count()
        assert new_page_count == original_page_count + 1
        assert resp['name'] == u'page'
        assert resp['content'] == self.md_contents
        assert resp['html'] == h.get_HTML_from_contents(self.md_contents, 'Markdown')
        assert response.content_type == 'application/json'

        # Invalid because name is empty and markup language is invalid
        params = self.page_create_params.copy()
        params.update({
            'name': u'',
            'markup_language': u'markdownable',
            'content': self.md_contents
        })
        params = json.dumps(params)
        response = self.app.post(url('pages'), params, self.json_headers, self.extra_environ_admin, status=400)
        resp = json.loads(response.body)
        assert resp['errors']['name'] == u'Please enter a value'
        assert resp['errors']['markup_language'] == \
            u"Value must be one of: Markdown; reStructuredText (not u'markdownable')"
        assert response.content_type == 'application/json'

        # Invalid because name is too long
        params = self.page_create_params.copy()
        params.update({
            'name': u'name' * 200,
            'markup_language': u'Markdown',
            'content': self.md_contents
        })
        params = json.dumps(params)
        response = self.app.post(url('pages'), params, self.json_headers, self.extra_environ_admin, status=400)
        resp = json.loads(response.body)
        assert resp['errors']['name'] == u'Enter a value not more than 255 characters long'
        assert response.content_type == 'application/json'
コード例 #13
0
ファイル: test_formsearches.py プロジェクト: jrwdunham/old
    def test_update(self):
        """Tests that PUT /formsearches/id updates the form search with id=id."""

        # Create a form search to update.
        query = {'filter': ['Form', 'transcription', 'regex', u'[a-g]{3,}']}
        params = self.form_search_create_params.copy()
        params.update({
            'name': u'form search',
            'description': u'This one\'s worth saving!',
            'search': query
        })
        params = json.dumps(params)
        response = self.app.post(url('formsearches'), params, self.json_headers, self.extra_environ_admin)
        resp = json.loads(response.body)
        form_search_count = Session.query(FormSearch).count()
        form_search_id = resp['id']
        original_datetime_modified = resp['datetime_modified']
        assert resp['name'] == u'form search'
        assert resp['description'] == u"This one's worth saving!"
        assert resp['search'] == query

        # Update the form search
        sleep(1)    # sleep for a second to ensure that MySQL registers a different datetime_modified for the update
        params = self.form_search_create_params.copy()
        params.update({
            'name': u'form search for keeping',
            'description': u'This one\'s worth saving!',
            'search': query
        })
        params = json.dumps(params)
        response = self.app.put(url('formsearch', id=form_search_id), params, self.json_headers,
                                 self.extra_environ_admin)
        resp = json.loads(response.body)
        datetime_modified = resp['datetime_modified']
        new_form_search_count = Session.query(FormSearch).count()
        assert form_search_count == new_form_search_count
        assert datetime_modified != original_datetime_modified
        assert response.content_type == 'application/json'

        # Attempt an update with no new input and expect to fail
        sleep(1)    # sleep for a second to ensure that MySQL could register a different datetime_modified for the update
        response = self.app.put(url('formsearch', id=form_search_id), params, self.json_headers,
                                 self.extra_environ_admin, status=400)
        resp = json.loads(response.body)
        form_search_count = new_form_search_count
        new_form_search_count = Session.query(FormSearch).count()
        our_form_search_datetime_modified = Session.query(FormSearch).get(form_search_id).datetime_modified
        assert our_form_search_datetime_modified.isoformat() == datetime_modified
        assert form_search_count == new_form_search_count
        assert resp['error'] == u'The update request failed because the submitted data were not new.'
        assert response.content_type == 'application/json'
コード例 #14
0
    def test_update(self):
        """Tests that PUT /elicitationmethods/id updates the elicitationmethod with id=id."""

        # Create an elicitation method to update.
        params = json.dumps({'name': u'name', 'description': u'description'})
        response = self.app.post(url('elicitationmethods'), params,
                                 self.json_headers, self.extra_environ_admin)
        resp = json.loads(response.body)
        elicitation_method_count = Session.query(ElicitationMethod).count()
        elicitation_method_id = resp['id']
        original_datetime_modified = resp['datetime_modified']

        # Update the elicitation method
        sleep(
            1
        )  # sleep for a second to ensure that MySQL registers a different datetime_modified for the update
        params = json.dumps({
            'name': u'name',
            'description': u'More content-ful description.'
        })
        response = self.app.put(
            url('elicitationmethod', id=elicitation_method_id), params,
            self.json_headers, self.extra_environ_admin)
        resp = json.loads(response.body)
        datetime_modified = resp['datetime_modified']
        new_elicitation_method_count = Session.query(ElicitationMethod).count()
        assert elicitation_method_count == new_elicitation_method_count
        assert datetime_modified != original_datetime_modified
        assert response.content_type == 'application/json'

        # Attempt an update with no new input and expect to fail
        sleep(
            1
        )  # sleep for a second to ensure that MySQL could register a different datetime_modified for the update
        response = self.app.put(url('elicitationmethod',
                                    id=elicitation_method_id),
                                params,
                                self.json_headers,
                                self.extra_environ_admin,
                                status=400)
        resp = json.loads(response.body)
        elicitation_method_count = new_elicitation_method_count
        new_elicitation_method_count = Session.query(ElicitationMethod).count()
        our_EM_datetime_modified = Session.query(ElicitationMethod).get(
            elicitation_method_id).datetime_modified
        assert our_EM_datetime_modified.isoformat() == datetime_modified
        assert elicitation_method_count == new_elicitation_method_count
        assert resp[
            'error'] == u'The update request failed because the submitted data were not new.'
        assert response.content_type == 'application/json'
コード例 #15
0
ファイル: test_speakers.py プロジェクト: FieldDB/old
    def test_update(self):
        """Tests that PUT /speakers/id updates the speaker with id=id."""

        # Create a speaker to update.
        params = self.speaker_create_params.copy()
        params.update({
            'first_name': u'first_name',
            'last_name': u'last_name',
            'page_content': u'page_content',
            'dialect': u'dialect'
        })
        params = json.dumps(params)
        response = self.app.post(url('speakers'), params, self.json_headers,
                                 self.extra_environ_admin)
        resp = json.loads(response.body)
        speaker_count = Session.query(Speaker).count()
        speaker_id = resp['id']
        original_datetime_modified = resp['datetime_modified']

        # Update the speaker
        sleep(1)    # sleep for a second to ensure that MySQL registers a different datetime_modified for the update
        params = self.speaker_create_params.copy()
        params.update({
            'first_name': u'first_name',
            'last_name': u'last_name',
            'page_content': u'page_content',
            'dialect': u'updated dialect.'
        })
        params = json.dumps(params)
        response = self.app.put(url('speaker', id=speaker_id), params, self.json_headers,
                                 self.extra_environ_admin)
        resp = json.loads(response.body)
        datetime_modified = resp['datetime_modified']
        new_speaker_count = Session.query(Speaker).count()
        assert speaker_count == new_speaker_count
        assert datetime_modified != original_datetime_modified
        assert response.content_type == 'application/json'

        # Attempt an update with no new input and expect to fail
        sleep(1)    # sleep for a second to ensure that MySQL could register a different datetime_modified for the update
        response = self.app.put(url('speaker', id=speaker_id), params, self.json_headers,
                                 self.extra_environ_admin, status=400)
        resp = json.loads(response.body)
        speaker_count = new_speaker_count
        new_speaker_count = Session.query(Speaker).count()
        our_speaker_datetime_modified = Session.query(Speaker).get(speaker_id).datetime_modified
        assert our_speaker_datetime_modified.isoformat() == datetime_modified
        assert speaker_count == new_speaker_count
        assert resp['error'] == u'The update request failed because the submitted data were not new.'
        assert response.content_type == 'application/json'
コード例 #16
0
ファイル: test_pages.py プロジェクト: dativebase/old
    def test_delete(self):
        """Tests that DELETE /pages/id deletes the page with id=id."""

        # Create a page to delete.
        params = self.page_create_params.copy()
        params.update({
            'name': u'page',
            'markup_language': u'Markdown',
            'content': self.md_contents
        })
        params = json.dumps(params)
        response = self.app.post(url('pages'), params, self.json_headers,
                                 self.extra_environ_admin)
        resp = json.loads(response.body)
        page_count = Session.query(Page).count()
        page_id = resp['id']

        # Now delete the page
        response = self.app.delete(url('page', id=page_id),
                                   headers=self.json_headers,
                                   extra_environ=self.extra_environ_admin)
        resp = json.loads(response.body)
        new_page_count = Session.query(Page).count()
        assert new_page_count == page_count - 1
        assert resp['id'] == page_id
        assert response.content_type == 'application/json'

        # Trying to get the deleted page from the db should return None
        deleted_page = Session.query(Page).get(page_id)
        assert deleted_page == None
        assert response.content_type == 'application/json'

        # Delete with an invalid id
        id = 9999999999999
        response = self.app.delete(url('page', id=id),
                                   headers=self.json_headers,
                                   extra_environ=self.extra_environ_admin,
                                   status=404)
        assert u'There is no page with id %s' % id in json.loads(
            response.body)['error']
        assert response.content_type == 'application/json'

        # Delete without an id
        response = self.app.delete(url('page', id=''),
                                   status=404,
                                   headers=self.json_headers,
                                   extra_environ=self.extra_environ_admin)
        assert json.loads(
            response.body)['error'] == 'The resource could not be found.'
コード例 #17
0
ファイル: test_pages.py プロジェクト: jrwdunham/old
    def test_update(self):
        """Tests that PUT /pages/id updates the page with id=id."""

        # Create a page to update.
        params = self.page_create_params.copy()
        params.update({
            'name': u'page',
            'markup_language': u'Markdown',
            'content': self.md_contents
        })
        params = json.dumps(params)
        response = self.app.post(url('pages'), params, self.json_headers, self.extra_environ_admin)
        resp = json.loads(response.body)
        page_count = Session.query(Page).count()
        page_id = resp['id']
        original_datetime_modified = resp['datetime_modified']

        # Update the page
        sleep(1)    # sleep for a second to ensure that MySQL registers a different datetime_modified for the update
        params = self.page_create_params.copy()
        params.update({
            'name': u'Awesome Page',
            'markup_language': u'Markdown',
            'content': self.md_contents
        })
        params = json.dumps(params)
        response = self.app.put(url('page', id=page_id), params, self.json_headers,
                                 self.extra_environ_admin)
        resp = json.loads(response.body)
        datetime_modified = resp['datetime_modified']
        new_page_count = Session.query(Page).count()
        assert page_count == new_page_count
        assert datetime_modified != original_datetime_modified
        assert resp['name'] == u'Awesome Page'
        assert response.content_type == 'application/json'

        # Attempt an update with no new input and expect to fail
        sleep(1)    # sleep for a second to ensure that MySQL could register a different datetime_modified for the update
        response = self.app.put(url('page', id=page_id), params, self.json_headers,
                                 self.extra_environ_admin, status=400)
        resp = json.loads(response.body)
        page_count = new_page_count
        new_page_count = Session.query(Page).count()
        our_page_datetime_modified = Session.query(Page).get(page_id).datetime_modified
        assert our_page_datetime_modified.isoformat() == datetime_modified
        assert page_count == new_page_count
        assert resp['error'] == u'The update request failed because the submitted data were not new.'
        assert response.content_type == 'application/json'
コード例 #18
0
ファイル: oldcollections.py プロジェクト: dativebase/old
    def index(self):
        """Get all collection resources.

        :URL: ``GET /collections`` with optional query string parameters for
            ordering and pagination.
        :returns: a list of all collection resources.

        .. note::

           See :func:`utils.add_order_by` and :func:`utils.add_pagination` for the
           query string parameters that effect ordering and pagination.

        .. note::
        
            ``GET /collections`` does not return the forms of the collections
            returned.  For that, a second request is required, i.e., to
            ``GET /collections/id`` with the relevant ``id`` value.

        """
        try:
            query = h.eagerload_collection(Session.query(Collection))
            query = h.add_order_by(query, dict(request.GET),
                                   self.query_builder)
            query = h.filter_restricted_models('Collection', query)
            return h.add_pagination(query, dict(request.GET))
        except Invalid, e:
            response.status_int = 400
            return {'errors': e.unpack_errors()}
コード例 #19
0
ファイル: pages.py プロジェクト: FieldDB/old
    def update(self, id):
        """Update a page and return it.
        
        :URL: ``PUT /pages/id``
        :Request body: JSON object representing the page with updated attribute values.
        :param str id: the ``id`` value of the page to be updated.
        :returns: the updated page model.

        """
        page = Session.query(Page).get(int(id))
        if page:
            try:
                schema = PageSchema()
                values = json.loads(unicode(request.body, request.charset))
                data = schema.to_python(values)
                page = update_page(page, data)
                # page will be False if there are no changes (cf. update_page).
                if page:
                    Session.add(page)
                    Session.commit()
                    return page
                else:
                    response.status_int = 400
                    return {'error':
                        u'The update request failed because the submitted data were not new.'}
            except h.JSONDecodeError:
                response.status_int = 400
                return  h.JSONDecodeErrorResponse
            except Invalid, e:
                response.status_int = 400
                return {'errors': e.unpack_errors()}
コード例 #20
0
ファイル: morphemelanguagemodels.py プロジェクト: FieldDB/old
    def update(self, id):
        """Update a morpheme language model and return it.

        :URL: ``PUT /morphemelanguagemodels/id``
        :Request body: JSON object representing the morpheme language model with updated attribute values.
        :param str id: the ``id`` value of the morpheme language model to be updated.
        :returns: the updated morpheme language model model.

        """
        morpheme_language_model = h.eagerload_morpheme_language_model(Session.query(MorphemeLanguageModel)).get(int(id))
        if morpheme_language_model:
            try:
                schema = MorphemeLanguageModelSchema()
                values = json.loads(unicode(request.body, request.charset))
                state = h.get_state_object(values)
                state.id = id
                data = schema.to_python(values, state)
                morpheme_language_model_dict = morpheme_language_model.get_dict()
                morpheme_language_model = update_morpheme_language_model(morpheme_language_model, data)
                # morpheme_language_model will be False if there are no changes (cf. update_morpheme_language_model).
                if morpheme_language_model:
                    backup_morpheme_language_model(morpheme_language_model_dict)
                    Session.add(morpheme_language_model)
                    Session.commit()
                    return morpheme_language_model
                else:
                    response.status_int = 400
                    return {'error': u'The update request failed because the submitted data were not new.'}
            except h.JSONDecodeError:
                response.status_int = 400
                return h.JSONDecodeErrorResponse
            except Invalid, e:
                response.status_int = 400
                return {'errors': e.unpack_errors()}
コード例 #21
0
ファイル: oldcollections.py プロジェクト: FieldDB/old
    def delete(self, id):
        """Delete an existing collection and return it.

        :URL: ``DELETE /collections/id``
        :param str id: the ``id`` value of the collection to be deleted.
        :returns: the deleted collection model.

        .. note::

           Only administrators and a collection's enterer can delete it.

        """
        collection = h.eagerload_collection(Session.query(Collection),
                                           eagerload_forms=True).get(id)
        if collection:
            if session['user'].role == u'administrator' or \
            collection.enterer is session['user']:
                session['user'] = Session.merge(session['user'])
                collection.modifier = session['user']
                collection_dict = collection.get_full_dict()
                backup_collection(collection_dict)
                update_collections_that_reference_this_collection(collection,
                                                self.query_builder, deleted=True)
                Session.delete(collection)
                Session.commit()
                return collection_dict
            else:
                response.status_int = 403
                return h.unauthorized_msg
        else:
            response.status_int = 404
            return {'error': 'There is no collection with id %s' % id}
コード例 #22
0
    def edit(self, id):
        """Return a user resource and the data needed to update it.

        :URL: ``GET /users/edit``
        :param str id: the ``id`` value of the user that will be updated.
        :returns: a dictionary of the form::

                {"user": {...}, "data": {...}}

            where the value of the ``user`` key is a dictionary representation
            of the user and the value of the ``user`` key is a dictionary of
            lists of resources.

        .. note::

           See :func:`get_new_user_data` to understand how the query string
           parameters can affect the contents of the lists in the returned
           dictionary.

        """
        user = Session.query(User).get(id)
        if user:
            data = get_new_user_data(request.GET)
            return {'data': data, 'user': user.get_full_dict()}
        else:
            response.status_int = 404
            return {'error': 'There is no user with id %s' % id}
コード例 #23
0
    def edit(self, id):
        """Return a morphological parser and the data needed to update it.

        :URL: ``GET /morphologicalparsers/id/edit``
        :param str id: the ``id`` value of the morphological parser that will be updated.
        :returns: a dictionary of the form::

                {"morphological_parser": {...}, "data": {...}}

            where the value of the ``morphological_parser`` key is a dictionary
            representation of the morphological_parser and the value of the ``data`` key
            is the data structure returned by the ``new`` action, i.e., a representation of
            the corpora, phonologies and morphologies in the system.

        """
        morphological_parser = h.eagerload_morphological_parser(
            Session.query(MorphologicalParser)).get(id)
        if morphological_parser:
            return {
                'data': get_data_for_new_edit(dict(request.GET)),
                'morphological_parser': morphological_parser
            }
        else:
            response.status_int = 404
            return {
                'error': 'There is no morphological parser with id %s' % id
            }
コード例 #24
0
    def serve_arpa(self, id):
        """Serve the generated ARPA file of the morpheme language model.

        :URL: ``PUT /morphemelanguagemodels/serve_arpa/id``
        :param str id: the ``id`` value of a morpheme language model.
        :returns: a stream of bytes -- the ARPA file of the LM.

        """
        lm = Session.query(MorphemeLanguageModel).get(id)
        if lm:
            arpa_path = lm.get_file_path('arpa')
            if os.path.isfile(arpa_path):
                if authorized_to_access_arpa_file(session['user'], lm):
                    return forward(
                        FileApp(arpa_path, content_type='text/plain'))
                else:
                    response.status_int = 403
                    return json.dumps(h.unauthorized_msg)
            else:
                response.status_int = 404
                return json.dumps({
                    'error':
                    'The ARPA file for morpheme language model %s has not been compiled yet.'
                    % id
                })
        else:
            response.status_int = 404
            return json.dumps({
                'error':
                'There is no morpheme language model with id %s' % id
            })
コード例 #25
0
ファイル: morphologicalparsers.py プロジェクト: FieldDB/old
    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()}
コード例 #26
0
ファイル: morphologies.py プロジェクト: jrwdunham/old
    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.'}
コード例 #27
0
ファイル: morphologicalparser.py プロジェクト: FieldDB/old
 def export(self):
     """Update the local store with the persistence layer and return the store.
     """
     persisted = dict((p.transcription, p.parse) for p in
         Session.query(Parse).filter(Parse.parser_id==self.parser.id).all())
     self._store.update(persisted)
     return self._store
コード例 #28
0
ファイル: morphologies.py プロジェクト: jrwdunham/old
    def show(self, id):
        """Return a morphology.

        :URL: ``GET /morphologies/id``
        :param str id: the ``id`` value of the morphology to be returned.
        :GET param str script: if set to '1', the script will be returned with the morphology
        :GET param str lexicon: if set to '1', the lexicon (dict) will be returned with the morphology
        :returns: a morphology model object.

        """
        morphology = h.eagerload_morphology(Session.query(Morphology)).get(id)
        if morphology:
            morphology_dict = morphology.get_dict()
            if request.GET.get('script') == u'1':
                morphology_script_path = morphology.get_file_path('script')
                if os.path.isfile(morphology_script_path):
                    morphology_dict['script'] = codecs.open(morphology_script_path, mode='r', encoding='utf8').read()
                else:
                    morphology_dict['script'] = u''
            if request.GET.get('lexicon') == u'1':
                morphology_lexicon_path = morphology.get_file_path('lexicon')
                if os.path.isfile(morphology_lexicon_path):
                    morphology_dict['lexicon'] = cPickle.load(open(morphology_lexicon_path, 'rb'))
                else:
                    morphology_dict['lexicon'] = {}
            return morphology_dict
        else:
            response.status_int = 404
            return {'error': 'There is no morphology with id %s' % id}
コード例 #29
0
    def servefile(self, id, file_id):
        """Return the corpus as a file in the format specified in the URL query string.

        :URL: ``PUT /corpora/id/servefile/file_id``.
        :param str id: the ``id`` value of the corpus.
        :param str file_id: the ``id`` value of the corpus file.
        :returns: the file data

        """
        corpus = Session.query(Corpus).get(id)
        if corpus:
            try:
                corpus_file = filter(lambda cf: cf.id == int(file_id),
                                     corpus.files)[0]
                corpus_file_path = os.path.join(get_corpus_dir_path(corpus),
                                                '%s.gz' % corpus_file.filename)
                if authorized_to_access_corpus_file(session['user'],
                                                    corpus_file):
                    return forward(
                        FileApp(corpus_file_path,
                                content_type='application/x-gzip'))
                else:
                    response.status_int = 403
                    return json.dumps(h.unauthorized_msg)
            except Exception:
                response.status_int = 400
                return json.dumps({
                    'error':
                    'Unable to serve corpus file %d of corpus %d' %
                    (file_id, id)
                })
        else:
            response.status_int = 404
            return json.dumps({'error': 'There is no corpus with id %s' % id})
コード例 #30
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})
コード例 #31
0
ファイル: users.py プロジェクト: jrwdunham/old
    def edit(self, id):
        """Return a user resource and the data needed to update it.

        :URL: ``GET /users/edit``
        :param str id: the ``id`` value of the user that will be updated.
        :returns: a dictionary of the form::

                {"user": {...}, "data": {...}}

            where the value of the ``user`` key is a dictionary representation
            of the user and the value of the ``user`` key is a dictionary of
            lists of resources.

        .. note::

           See :func:`get_new_user_data` to understand how the query string
           parameters can affect the contents of the lists in the returned
           dictionary.

        """
        user = Session.query(User).get(id)
        if user:
            data = get_new_user_data(request.GET)
            return {'data': data, 'user': user.get_full_dict()}
        else:
            response.status_int = 404
            return {'error': 'There is no user with id %s' % id}
コード例 #32
0
    def get_probabilities(self, id):
        """Return the probability of each sequence of morphemes passed in the JSON PUT params.

        :param list morpheme_sequences: space-delimited morphemes in form|gloss|category
            format wherer "|" is actually ``h.rare_delimiter``.
        :returns: a dictionary with morpheme sequences as keys and log probabilities as values.

        """
        lm = Session.query(MorphemeLanguageModel).get(id)
        if lm:
            try:
                schema = MorphemeSequencesSchema()
                values = json.loads(unicode(request.body, request.charset))
                data = schema.to_python(values)
                morpheme_sequences = [
                    h.normalize(ms) for ms in data['morpheme_sequences']
                ]
                return lm.get_probabilities(morpheme_sequences)
            except h.JSONDecodeError:
                response.status_int = 400
                return h.JSONDecodeErrorResponse
            except Invalid, e:
                response.status_int = 400
                return {'errors': e.unpack_errors()}
            except Exception:
                response.status_int = 400
                return {
                    'error':
                    'An error occurred while trying to generate probabilities.'
                }
コード例 #33
0
ファイル: syntacticcategories.py プロジェクト: jrwdunham/old
    def update(self, id):
        """Update a syntactic category and return it.
        
        :URL: ``PUT /syntacticcategorys/id``
        :Request body: JSON object representing the syntactic category with updated attribute values.
        :param str id: the ``id`` value of the syntactic category to be updated.
        :returns: the updated syntactic category model.

        """
        syntactic_category = Session.query(SyntacticCategory).get(int(id))
        if syntactic_category:
            try:
                old_name = syntactic_category.name
                schema = SyntacticCategorySchema()
                values = json.loads(unicode(request.body, request.charset))
                state = h.get_state_object(values)
                state.id = id
                data = schema.to_python(values, state)
                syntactic_category = update_syntactic_category(syntactic_category, data)
                # syntactic_category will be False if there are no changes (cf. update_syntactic_category).
                if syntactic_category:
                    Session.add(syntactic_category)
                    Session.commit()
                    if syntactic_category.name != old_name:
                        update_forms_referencing_this_category(syntactic_category)
                    return syntactic_category
                else:
                    response.status_int = 400
                    return {"error": u"The update request failed because the submitted data were not new."}
            except h.JSONDecodeError:
                response.status_int = 400
                return h.JSONDecodeErrorResponse
            except Invalid, e:
                response.status_int = 400
                return {"errors": e.unpack_errors()}
コード例 #34
0
    def edit(self, id):
        """Return a morpheme language model and the data needed to update it.

        :URL: ``GET /morphemelanguagemodels/id/edit``
        :param str id: the ``id`` value of the morpheme language model that will be updated.
        :returns: a dictionary of the form::

                {"morpheme_language_model": {...}, "data": {...}}

            where the value of the ``morpheme_language_model`` key is a dictionary
            representation of the morpheme_language_model and the value of the ``data`` key
            is the data structure returned by the ``new`` action.

        """
        lm = h.eagerload_morpheme_language_model(
            Session.query(MorphemeLanguageModel)).get(id)
        if lm:
            return {
                'data': get_data_for_new_edit(dict(request.GET)),
                'morpheme_language_model': lm
            }
        else:
            response.status_int = 404
            return {
                'error': 'There is no morpheme language model with id %s' % id
            }
コード例 #35
0
ファイル: files.py プロジェクト: dativebase/old
def serve_file(id, reduced=False):
    """Serve the content (binary data) of a file.
    
    :param str id: the ``id`` value of the file whose file data will be served.
    :param bool reduced: toggles serving of file data or reduced-size file data.

    """
    file = Session.query(File).options(subqueryload(File.parent_file)).get(id)
    if getattr(file, 'parent_file', None):
        file = file.parent_file
    elif getattr(file, 'url', None):
        response.status_int = 400
        return json.dumps({'error': u'The content of file %s is stored elsewhere at %s' % (id, file.url)})
    if file:
        files_dir = h.get_OLD_directory_path('files', config=config)
        if reduced:
            filename = getattr(file, 'lossy_filename', None)
            if not filename:
                response.status_int = 404
                return json.dumps({'error': u'There is no size-reduced copy of file %s' % id})
            file_path = os.path.join(files_dir, 'reduced_files', filename)
        else:
            file_path = os.path.join(files_dir, file.filename)
        unrestricted_users = h.get_unrestricted_users()
        if h.user_is_authorized_to_access_model(session['user'], file, unrestricted_users):
            return forward(FileApp(file_path))
        else:
            response.status_int = 403
            return json.dumps(h.unauthorized_msg)
    else:
        response.status_int = 404
        return json.dumps({'error': 'There is no file with id %s' % id})
コード例 #36
0
ファイル: phonologies.py プロジェクト: dativebase/old
    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.'}
コード例 #37
0
    def search(self, id):
        """Return the remembered forms of a user that match the input JSON query.

        :URL: ``SEARCH /rememberedforms/id`` (or ``POST /rememberedforms/id/search``).
        :param str id: the ``id`` value of the user whose remembered forms are searched.
        :request body: A JSON object of the form::

                {"query": {"filter": [ ... ], "order_by": [ ... ]},
                 "paginator": { ... }}

            where the ``order_by`` and ``paginator`` attributes are optional.

        """
        user = Session.query(User).get(id)
        if user:
            try:
                json_search_params = unicode(request.body, request.charset)
                python_search_params = json.loads(json_search_params)
                query = h.eagerload_form(
                    self.query_builder.get_SQLA_query(
                        python_search_params.get('query')))
                query = query.filter(Form.memorizers.contains(user))
                query = h.filter_restricted_models('Form', query)
                return h.add_pagination(query,
                                        python_search_params.get('paginator'))
            except h.JSONDecodeError:
                response.status_int = 400
                return h.JSONDecodeErrorResponse
            except (OLDSearchParseError, Invalid), e:
                response.status_int = 400
                return {'errors': e.unpack_errors()}
            except:
コード例 #38
0
    def show(self, id):
        """Return a morphological parser.

        :URL: ``GET /morphologicalparsers/id``
        :param str id: the ``id`` value of the morphological parser to be returned.
        :GET param str script: if set to '1', the script will be returned with the morphological parser
        :returns: a morphological parser model object.

        """
        morphological_parser = h.eagerload_morphological_parser(
            Session.query(MorphologicalParser)).get(id)
        if morphological_parser:
            morphological_parser_dict = morphological_parser.get_dict()
            if request.GET.get('script') == u'1':
                morphological_parser_dir_path = h.get_model_directory_path(
                    morphological_parser, config)
                morphological_parser_script_path = h.get_model_file_path(
                    morphological_parser,
                    morphological_parser_dir_path,
                    file_type='script')
                if os.path.isfile(morphological_parser_script_path):
                    morphological_parser_dict['script'] = codecs.open(
                        morphological_parser_script_path,
                        mode='r',
                        encoding='utf8').read()
                else:
                    morphological_parser_dict['script'] = u''
            return morphological_parser_dict
        else:
            response.status_int = 404
            return {
                'error': 'There is no morphological parser with id %s' % id
            }
コード例 #39
0
ファイル: phonologies.py プロジェクト: dativebase/old
    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}
コード例 #40
0
    def generate(self, id):
        """Generate the files that constitute the morpheme language model, crucially the file that holds the pickled LM trie.

        :URL: ``PUT /morpheme_language_model/id/generate``
        :param str id: the ``id`` value of the morpheme language model whose files will be generated.
        :returns: the morpheme language model is returned;  ``GET /morpheme_language_model/id`` must be polled to
            determine when the generation task has terminated.

        """
        lm = Session.query(MorphemeLanguageModel).get(id)
        if not lm:
            response.status_int = 404
            return {
                'error': 'There is no morpheme language model with id %s' % id
            }
        args = {
            'morpheme_language_model_id': lm.id,
            'user_id': session['user'].id,
            'timeout': h.morpheme_language_model_generate_timeout
        }
        foma_worker_q.put({
            'id': h.generate_salt(),
            'func': 'generate_language_model',
            'args': args
        })
        return lm
コード例 #41
0
    def get_probabilities(self, id):
        """Return the probability of each sequence of morphemes passed in the JSON PUT params.

        :param list morpheme_sequences: space-delimited morphemes in form|gloss|category
            format wherer "|" is actually ``h.rare_delimiter``.
        :returns: a dictionary with morpheme sequences as keys and log probabilities as values.

        """
        lm = Session.query(MorphemeLanguageModel).get(id)
        if lm:
            try:
                schema = MorphemeSequencesSchema()
                values = json.loads(unicode(request.body, request.charset))
                data = schema.to_python(values)
                morpheme_sequences = [h.normalize(ms) for ms in data['morpheme_sequences']]
                return lm.get_probabilities(morpheme_sequences)
            except h.JSONDecodeError:
                response.status_int = 400
                return h.JSONDecodeErrorResponse
            except Invalid, e:
                response.status_int = 400
                return {'errors': e.unpack_errors()}
            except Exception:
                response.status_int = 400
                return {'error': 'An error occurred while trying to generate probabilities.'}
コード例 #42
0
ファイル: orthographies.py プロジェクト: GracefulLemming/old
    def delete(self, id):
        """Delete an existing orthography and return it.

        :URL: ``DELETE /orthographies/id``
        :param str id: the ``id`` value of the orthography to be deleted.
        :returns: the deleted orthography model.

        .. note::
        
            Contributors can only delete orthographies that are not used in the
            active application settings.

        """
        orthography = Session.query(Orthography).get(id)
        if orthography:
            app_set = h.get_application_settings()
            if session['user'].role == u'administrator' or orthography not in (
                    app_set.storage_orthography, app_set.input_orthography,
                    app_set.output_orthography):
                Session.delete(orthography)
                Session.commit()
                return orthography
            else:
                response.status = 403
                return {
                    'error':
                    u'Only administrators are permitted to delete orthographies that are used in the active application settings.'
                }
        else:
            response.status_int = 404
            return {'error': 'There is no orthography with id %s' % id}
コード例 #43
0
ファイル: oldcollections.py プロジェクト: FieldDB/old
    def index(self):
        """Get all collection resources.

        :URL: ``GET /collections`` with optional query string parameters for
            ordering and pagination.
        :returns: a list of all collection resources.

        .. note::

           See :func:`utils.add_order_by` and :func:`utils.add_pagination` for the
           query string parameters that effect ordering and pagination.

        .. note::
        
            ``GET /collections`` does not return the forms of the collections
            returned.  For that, a second request is required, i.e., to
            ``GET /collections/id`` with the relevant ``id`` value.

        """
        try:
            query = h.eagerload_collection(Session.query(Collection))
            query = h.add_order_by(query, dict(request.GET), self.query_builder)
            query = h.filter_restricted_models('Collection', query)
            return h.add_pagination(query, dict(request.GET))
        except Invalid, e:
            response.status_int = 400
            return {'errors': e.unpack_errors()}
コード例 #44
0
ファイル: applicationsettings.py プロジェクト: jrwdunham/old
    def edit(self, id):
        """Return an application settings and the data needed to update it.

        :URL: ``GET /applicationsettings/edit`` with optional query string parameters 
        :param str id: the ``id`` value of the application settings that will be updated.
        :returns: a dictionary of the form::

                {"application_settings": {...}, "data": {...}}

            where the value of the ``application_settings`` key is a dictionary
            representation of the application settings and the value of the
            ``data`` key is a dictionary containing the objects necessary to
            update an application settings, viz. the return value of
            :func:`ApplicationsettingsController.new`.

        .. note::
        
           This action can be thought of as a combination of
           :func:`ApplicationsettingsController.show` and
           :func:`ApplicationsettingsController.new`.  See
           :func:`get_new_application_settings_data` to understand how the query
           string parameters can affect the contents of the lists in the
           ``data`` dictionary.

        """

        application_settings = h.eagerload_application_settings(
            Session.query(ApplicationSettings)).get(id)
        if application_settings:
            return {'data': get_new_application_settings_data(request.GET),
                    'application_settings': application_settings}
        else:
            response.status_int = 404
            return {'error': 'There is no application settings with id %s' % id}
コード例 #45
0
ファイル: oldcollections.py プロジェクト: FieldDB/old
    def show(self, id):
        """Return a collection.
        
        :URL: ``GET /collections/id``
        :param str id: the ``id`` value of the collection to be returned.
        :returns: a collection model object.

        .. note::

            Returns all of the forms of the collection, unlike the other
            collections actions.

        """
        collection = h.eagerload_collection(Session.query(Collection),
                                           eagerload_forms=True).get(id)
        if collection:
            unrestricted_users = h.get_unrestricted_users()
            user = session['user']
            if h.user_is_authorized_to_access_model(user, collection, unrestricted_users):
                return collection.get_full_dict()
            else:
                response.status_int = 403
                return h.unauthorized_msg
        else:
            response.status_int = 404
            return {'error': 'There is no collection with id %s' % id}
コード例 #46
0
ファイル: corpora.py プロジェクト: jrwdunham/old
    def servefile(self, id, file_id):
        """Return the corpus as a file in the format specified in the URL query string.

        :URL: ``PUT /corpora/id/servefile/file_id``.
        :param str id: the ``id`` value of the corpus.
        :param str file_id: the ``id`` value of the corpus file.
        :returns: the file data

        """
        corpus = Session.query(Corpus).get(id)
        if corpus:
            try:
                corpus_file = filter(lambda cf: cf.id == int(file_id), corpus.files)[0]
                corpus_file_path = os.path.join(get_corpus_dir_path(corpus),
                                              '%s.gz' % corpus_file.filename)
                if authorized_to_access_corpus_file(session['user'], corpus_file):
                    return forward(FileApp(corpus_file_path, content_type='application/x-gzip'))
                else:
                    response.status_int = 403
                    return json.dumps(h.unauthorized_msg)
            except Exception:
                response.status_int = 400
                return json.dumps({'error': 'Unable to serve corpus file %d of corpus %d' % (
                        file_id, id)})
        else:
            response.status_int = 404
            return json.dumps({'error': 'There is no corpus with id %s' % id})
コード例 #47
0
ファイル: oldcollections.py プロジェクト: dativebase/old
    def delete(self, id):
        """Delete an existing collection and return it.

        :URL: ``DELETE /collections/id``
        :param str id: the ``id`` value of the collection to be deleted.
        :returns: the deleted collection model.

        .. note::

           Only administrators and a collection's enterer can delete it.

        """
        collection = h.eagerload_collection(Session.query(Collection),
                                            eagerload_forms=True).get(id)
        if collection:
            if session['user'].role == u'administrator' or \
            collection.enterer is session['user']:
                session['user'] = Session.merge(session['user'])
                collection.modifier = session['user']
                collection_dict = collection.get_full_dict()
                backup_collection(collection_dict)
                update_collections_that_reference_this_collection(
                    collection, self.query_builder, deleted=True)
                Session.delete(collection)
                Session.commit()
                return collection_dict
            else:
                response.status_int = 403
                return h.unauthorized_msg
        else:
            response.status_int = 404
            return {'error': 'There is no collection with id %s' % id}
コード例 #48
0
ファイル: morphologicalparsers.py プロジェクト: jrwdunham/old
    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()}
コード例 #49
0
ファイル: formsearches.py プロジェクト: dativebase/old
    def edit(self, id):
        """GET /formsearches/id/edit: Return the data necessary to update an existing
        OLD form search.
        """
        """Return a form search and the data needed to update it.

        :URL: ``GET /formsearches/edit`` with optional query string parameters 
        :param str id: the ``id`` value of the form search that will be updated.
        :returns: a dictionary of the form::

                {"form_search": {...}, "data": {...}}

            where the value of the ``form_search`` key is a dictionary
            representation of the form search and the value of the ``data`` key
            is a dictionary containing the data necessary to update a form
            search.

        """
        form_search = h.eagerload_form_search(
            Session.query(FormSearch)).get(id)
        if form_search:
            data = {
                'search_parameters':
                h.get_search_parameters(self.query_builder)
            }
            return {'data': data, 'form_search': form_search}
        else:
            response.status_int = 404
            return {'error': 'There is no form search with id %s' % id}
コード例 #50
0
ファイル: morphologicalparsers.py プロジェクト: jrwdunham/old
 def export_deprecated(self, id):
     """Export the parser as a self-contained archive including a Python interface and all required files.
     """
     try:
         parser = Session.query(MorphologicalParser).get(id)
         directory = parser.directory
         archive_dir = os.path.join(directory, 'archive')
         if os.path.exists(archive_dir):
             rmtree(archive_dir)
         os.mkdir(archive_dir)
         parser.copy_files(archive_dir)
         parser.phonology.copy_files(archive_dir)
         parser.morphology.copy_files(archive_dir)
         parser.language_model.copy_files(archive_dir)
         lib_path = os.path.join(config['here'], 'onlinelinguisticdatabase', 'lib')
         simplelm_path = os.path.join(lib_path, 'simplelm')
         parser_path = os.path.join(lib_path, 'parser.py')
         parse_path = os.path.join(lib_path, 'parse.py')
         new_parse_path = os.path.join(archive_dir, 'parse.py')
         copytree(simplelm_path, os.path.join(archive_dir, 'simplelm'))
         copyfile(parser_path, os.path.join(archive_dir, 'parser.py'))
         copyfile(parse_path, new_parse_path)
         os.chmod(new_parse_path, 0744)
         data = parser.export()
         data_path = os.path.join(archive_dir, 'data.pickle')
         cPickle.dump(data, open(data_path, 'wb'))
         zip_path = h.zipdir(archive_dir)
         return forward(FileApp(zip_path))
     except Exception, e:
         log.warn(e)
         response.status_int = 400
         return json.dumps({'error': 'An error occured while attempting to export '
                            'morphological parser %s' % id})
コード例 #51
0
ファイル: pages.py プロジェクト: dativebase/old
    def edit(self, id):
        """Return a page and the data needed to update it.

        :URL: ``GET /pages/edit``
        :param str id: the ``id`` value of the page that will be updated.
        :returns: a dictionary of the form::

                {"page": {...}, "data": {...}}

            where the value of the ``page`` key is a dictionary
            representation of the page and the value of the ``data`` key
            is the list of valid markup language names.

        """
        page = Session.query(Page).get(id)
        if page:
            return {
                'data': {
                    'markup_languages': h.markup_languages
                },
                'page': page
            }
        else:
            response.status_int = 404
            return {'error': 'There is no page with id %s' % id}
コード例 #52
0
ファイル: sources.py プロジェクト: dativebase/old
    def update(self, id):
        """Update a source and return it.
        
        :URL: ``PUT /sources/id``
        :Request body: JSON object representing the source with updated attribute values.
        :param str id: the ``id`` value of the source to be updated.
        :returns: the updated source model.

        """
        source = Session.query(Source).get(int(id))
        if source:
            try:
                schema = SourceSchema()
                values = json.loads(unicode(request.body, request.charset))
                state = h.get_state_object(values)
                state.id = id
                data = schema.to_python(values, state)
                source = update_source(source, data)
                # source will be False if there are no changes (cf. update_source).
                if source:
                    Session.add(source)
                    Session.commit()
                    return source
                else:
                    response.status_int = 400
                    return {'error':
                        u'The update request failed because the submitted data were not new.'}
            except h.JSONDecodeError:
                response.status_int = 400
                return h.JSONDecodeErrorResponse
            except Invalid, e:
                response.status_int = 400
                return {'errors': e.unpack_errors()}
コード例 #53
0
ファイル: rememberedforms.py プロジェクト: jrwdunham/old
    def search(self, id):
        """Return the remembered forms of a user that match the input JSON query.

        :URL: ``SEARCH /rememberedforms/id`` (or ``POST /rememberedforms/id/search``).
        :param str id: the ``id`` value of the user whose remembered forms are searched.
        :request body: A JSON object of the form::

                {"query": {"filter": [ ... ], "order_by": [ ... ]},
                 "paginator": { ... }}

            where the ``order_by`` and ``paginator`` attributes are optional.

        """
        user = Session.query(User).get(id)
        if user:
            try:
                json_search_params = unicode(request.body, request.charset)
                python_search_params = json.loads(json_search_params)
                query = h.eagerload_form(
                    self.query_builder.get_SQLA_query(python_search_params.get('query')))
                query = query.filter(Form.memorizers.contains(user))
                query = h.filter_restricted_models('Form', query)
                return h.add_pagination(query, python_search_params.get('paginator'))
            except h.JSONDecodeError:
                response.status_int = 400
                return h.JSONDecodeErrorResponse
            except (OLDSearchParseError, Invalid), e:
                response.status_int = 400
                return {'errors': e.unpack_errors()}
            except:
コード例 #54
0
ファイル: files.py プロジェクト: dativebase/old
    def edit(self, id):
        """Return a file and the data needed to update it.

        :URL: ``GET /files/edit`` with optional query string parameters 
        :param str id: the ``id`` value of the file that will be updated.
        :returns: a dictionary of the form::

                {"file": {...}, "data": {...}}

            where the value of the ``file`` key is a dictionary representation
            of the file and the value of the ``data`` key is a dictionary
            containing the objects necessary to update a file, viz. the return
            value of :func:`FilesController.new`

        .. note::
        
           This action can be thought of as a combination of
           :func:`FilesController.show` and :func:`FilesController.new`.  See
           :func:`get_new_edit_file_data` to understand how the query string
           parameters can affect the contents of the lists in the ``data``
           dictionary.

        """
        response.content_type = 'application/json'
        file = h.eagerload_file(Session.query(File)).get(id)
        if file:
            unrestricted_users = h.get_unrestricted_users()
            if h.user_is_authorized_to_access_model(session['user'], file, unrestricted_users):
                return {'data': get_new_edit_file_data(request.GET), 'file': file}
            else:
                response.status_int = 403
                return h.unauthorized_msg
        else:
            response.status_int = 404
            return {'error': 'There is no file with id %s' % id}
コード例 #55
0
ファイル: applicationsettings.py プロジェクト: jrwdunham/old
    def update(self, id):
        """Update an application settings and return it.
        
        :URL: ``PUT /applicationsettings/id``
        :Request body: JSON object representing the application settings with updated attribute values.
        :param str id: the ``id`` value of the application settings to be updated.
        :returns: the updated application settings model.

        """
        application_settings = h.eagerload_application_settings(
            Session.query(ApplicationSettings)).get(int(id))
        if application_settings:
            try:
                schema = ApplicationSettingsSchema()
                values = json.loads(unicode(request.body, request.charset))
                data = schema.to_python(values)
                # Try to create an updated ApplicationSetting object.
                application_settings = update_application_settings(application_settings, data)
                # application_settings will be False if there are no changes
                if application_settings:
                    Session.add(application_settings)
                    Session.commit()
                    app_globals.application_settings = h.ApplicationSettings()
                    return application_settings
                else:
                    response.status_int = 400
                    return {'error': 'The update request failed because the submitted data were not new.'}
            except h.JSONDecodeError:
                response.status_int = 400
                return h.JSONDecodeErrorResponse
            except Invalid, e:
                response.status_int = 400
                return {'errors': e.unpack_errors()}
コード例 #56
0
ファイル: speakers.py プロジェクト: dativebase/old
    def edit(self, id):
        """Return a speaker resource and the data needed to update it.

        :URL: ``GET /speakers/edit``
        :param str id: the ``id`` value of the speaker that will be updated.
        :returns: a dictionary of the form::

                {"speaker": {...}, "data": {...}}

            where the value of the ``speaker`` key is a dictionary
            representation of the speaker and the value of the ``data`` key
            is an empty dictionary.

        TODO: implement a `get_new_speaker_data` function here, similar to that
        defined in controllers/user.py so that GET params can effect what data
        are returned.

        """
        speaker = Session.query(Speaker).get(id)
        if speaker:
            return {
                'data': {'markup_languages': h.markup_languages},
                'speaker': speaker
            }
        else:
            response.status_int = 404
            return {'error': 'There is no speaker with id %s' % id}