def _createSessionObject(self, sessionForm):
        """Create Session object, returning SessionForm."""
        # make sure user is authenticated
        user = endpoints.get_current_user()
        if not user:
            raise endpoints.UnauthorizedException('Authorization required')

        # get the conference
        conf = ndb.Key(urlsafe=sessionForm.websafeConferenceKey).get()
        if not conf:
            raise endpoints.NotFoundException('No conference found with key: %s' % sessionForm.conferenceKey)

        # check ownership
        if getUserId(user) != conf.organizerUserId:
            raise endpoints.ForbiddenException('Only the organizer of this conference can add sessions.')

        # copy SessionForm/ProtoRPC Message into dict
        data = formToDict(sessionForm, exclude=('websafeKey', 'websafeConferenceKey'))
        # check required fields
        for key in Session.required_fields_schema:
            if not data[key]:
                raise endpoints.BadRequestException("'%s' field is required to create a session." % key)

        # convert date string to a datetime object.
        try:
            data['date'] = datetime.strptime(data['date'][:10], "%Y-%m-%d").date()
        except (TypeError, ValueError):
            raise endpoints.BadRequestException("Invalid date format. Please use 'YYYY-MM-DD'")

        # convert date string to a time object. HH:MM
        try:
            data['startTime'] = datetime.strptime(data['startTime'][:5], "%H:%M").time()
        except (TypeError, ValueError):
            raise endpoints.BadRequestException("Invalid date format. Please use 'HH:MM'")

        if data['duration'] <= 0:
            raise endpoints.BadRequestException("Duration must be greater than zero")

        if data['date'] < conf.startDate or data['date'] > conf.endDate:
            raise endpoints.BadRequestException("Session must be within range of conference start and end date")

        data['speaker'] = Speaker(name=data['speaker'])
        # ask Datastore to allocate an ID.
        s_id = Session.allocate_ids(size=1, parent=conf.key)[0]
        # Datastore returns an integer ID that we can use to create a session key
        data['key'] = ndb.Key(Session, s_id, parent=conf.key)
        # Add session to datastore
        session = Session(**data)
        session.put()

        # Add a task to check and update new featured speaker
        taskqueue.add(
            params={'websafeConferenceKey': conf.key.urlsafe(), 'speaker': session.speaker.name},
            url='/tasks/set_featured_speaker'
        )

        return session.toForm()
    def _createConferenceObject(self, conferenceForm):
        """Create conference object, returns ConferenceForm."""

        user = endpoints.get_current_user()
        if not user:
            raise endpoints.UnauthorizedException('Authorization required')

        data = formToDict(conferenceForm, exclude=('websafeKey', 'organizerDisplayName'))
        # add default values for those missing
        for df in DEFAULTS:
            if data[df] in (None, []):
                data[df] = DEFAULTS[df]

        # add organizerUserId before checking the required fields
        data['organizerUserId'] = user_id = getUserId(user)

        # check required fields
        for key in Conference.required_fields_schema:
            if not data[key]:
                raise endpoints.BadRequestException("Conference '%s' field required" % key)

        # convert dates from strings to Date objects; set month based on start_date
        try:
            data['startDate'] = datetime.strptime(data['startDate'][:10], "%Y-%m-%d").date()
            data['endDate'] = datetime.strptime(data['endDate'][:10], "%Y-%m-%d").date()
        except (TypeError, ValueError):
            raise endpoints.BadRequestException("Invalid date format. Please use 'YYYY-MM-DD'")

        if data['startDate'] > data['endDate']:
            raise endpoints.BadRequestException("start date must be before end date")
        data['month'] = data['startDate'].month

        # set seatsAvailable to be same as maxAttendees on creation
        if data["maxAttendees"] > 0:
            data["seatsAvailable"] = data["maxAttendees"]

        # generate Profile Key based on user ID and Conference
        # ID based on Profile key get Conference key from ID
        p_key = ndb.Key(Profile, user_id)
        c_id = Conference.allocate_ids(size=1, parent=p_key)[0]
        c_key = ndb.Key(Conference, c_id, parent=p_key)
        data['key'] = c_key

        # create Conference, send email to organizer confirming
        # creation of Conference & return (modified) ConferenceForm
        conf = Conference(**data)
        conf.put()
        taskqueue.add(
            params={'email': user.email(), 'conferenceInfo': repr(conferenceForm)},
            url='/tasks/send_confirmation_email'
        )
        return conf.toForm()
    def testUpdateConference(self):
        """ TEST: Update conference w/provided fields & return w/updated info """
        self.initDatabase()

        self.login()
        conf = Conference.query(ancestor=ndb.Key(Profile, self.getUserId())).get()
        key = conf.key
        assert conf.name != 'testUpdateConference', "This shouldn't fail. Maybe someone messed with database fixture"

        # converting `conf` to a dictionary doesn't format the values properly to send request.
        # so first convert it to a form, then to a dictionary
        data = formToDict(conf.toForm())
        data['name'] = 'testUpdateConference'
        container = CONF_POST_REQUEST.combined_message_class(
            websafeConferenceKey=conf.key.urlsafe(),
            **data
        )

        r = self.api.updateConference(container)
        assert r.name == 'testUpdateConference', 'Returned an invalid conference'
        assert r.name == key.get().name, 'Failed to update datastore'