text: #!/usr/bin/env python
  
  """
  conference.py -- Udacity conference server-side Python App Engine API;
      uses Google Cloud Endpoints
  
  $Id: conference.py,v 1.25 2014/05/24 23:42:19 wesc Exp wesc $
  
  created by wesc on 2014 apr 21
  
  """
  
  __author__ = 'wesc+api@google.com (Wesley Chun)'
  
  
  from datetime import datetime
  
  import endpoints
  from protorpc import messages
  from protorpc import message_types
  from protorpc import remote
  
  from google.appengine.ext import ndb
  
  from models import Profile
  from models import ProfileMiniForm
  from models import ProfileForm
  from models import TeeShirtSize
  
  from utils import getUserId
  
  from settings import WEB_CLIENT_ID
  
  EMAIL_SCOPE = endpoints.EMAIL_SCOPE
  API_EXPLORER_CLIENT_ID = endpoints.API_EXPLORER_CLIENT_ID
  
  # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  
  
  @endpoints.api( name='conference',
                  version='v1',
                  allowed_client_ids=[WEB_CLIENT_ID, API_EXPLORER_CLIENT_ID],
                  scopes=[EMAIL_SCOPE])
  class ConferenceApi(remote.Service):
      """Conference API v0.1"""
  
  # - - - Profile objects - - - - - - - - - - - - - - - - - - -
  
      def _copyProfileToForm(self, prof):
          """Copy relevant fields from Profile to ProfileForm."""
          # copy relevant fields from Profile to ProfileForm
          pf = ProfileForm()
          for field in pf.all_fields():
              if hasattr(prof, field.name):
                  # convert t-shirt string to Enum; just copy others
                  if field.name == 'teeShirtSize':
                      setattr(pf, field.name, getattr(TeeShirtSize, getattr(prof, field.name)))
                  else:
                      setattr(pf, field.name, getattr(prof, field.name))
          pf.check_initialized()
          return pf
  
  
      def _getProfileFromUser(self):
          """Return user Profile from datastore, creating new one if non-existent."""
          user = endpoints.get_current_user()
          if not user:
              raise endpoints.UnauthorizedException('Authorization required')
  
          # get Profile from datastore
          user_id = getUserId(user)
          p_key = ndb.Key(Profile, user_id)
          profile = p_key.get()
          # create new Profile if not there
          if not profile:
              profile = Profile(
                  key = p_key,
                  displayName = user.nickname(),
                  mainEmail= user.email(),
                  teeShirtSize = str(TeeShirtSize.NOT_SPECIFIED),
              )
              profile.put()
  
          return profile      # return Profile
  
  
      def _doProfile(self, save_request=None):
          """Get user Profile and return to user, possibly updating it first."""
          # get user Profile
          prof = self._getProfileFromUser()
  
          # if saveProfile(), process user-modifyable fields
          if save_request:
              for field in ('displayName', 'teeShirtSize'):
                  if hasattr(save_request, field):
                      val = getattr(save_request, field)
                      if val:
                          setattr(prof, field, str(val))
              prof.put()
  
          # return ProfileForm
          return self._copyProfileToForm(prof)
  
  
      @endpoints.method(message_types.VoidMessage, ProfileForm,
              path='profile', http_method='GET', name='getProfile')
      def getProfile(self, request):
          """Return user profile."""
          return self._doProfile()
  
  
      @endpoints.method(ProfileMiniForm, ProfileForm,
              path='profile', http_method='POST', name='saveProfile')
      def saveProfile(self, request):
          """Update & return user profile."""
          return self._doProfile(request)
  
  
  # - - - Conference objects - - - - - - - - - - - - - - - - - - -
  
  # TODO
  
  # registers API
  api = endpoints.api_server([ConferenceApi]) 
  