
Gc           @   s  d  Z  d Z d d k Z d d k Z d d k Z y d d k l Z WnI e j
 o= y d d k Z Wn# e j
 o d d k	 l Z n Xn Xd d k
 Z d d k Z d d k Z d Z d Z d Z d	 e f d
     YZ d e f d     YZ d e f d     YZ d e f d     YZ d e f d     YZ d e f d     YZ d e f d     YZ d e i i f d     YZ d e f d     YZ d S(   s  GDataService provides CRUD ops. and programmatic login for GData services.

  Error: A base exception class for all exceptions in the gdata_client
         module.

  CaptchaRequired: This exception is thrown when a login attempt results in a
                   captcha challenge from the ClientLogin service. When this
                   exception is thrown, the captcha_token and captcha_url are
                   set to the values provided in the server's response.

  BadAuthentication: Raised when a login attempt is made with an incorrect
                     username or password.

  NotAuthenticated: Raised if an operation requiring authentication is called
                    before a user has authenticated.

  NonAuthSubToken: Raised if a method to modify an AuthSub token is used when
                   the user is either not authenticated or is authenticated
                   through programmatic login.

  RequestError: Raised if a CRUD request returned a non-success code. 

  UnexpectedReturnType: Raised if the response from the server was not of the
                        desired type. For example, this would be raised if the
                        server sent a feed when the client requested an entry.

  GDataService: Encapsulates user credentials needed to perform insert, update
                and delete operations with the GData API. An instance can
                perform user authentication, query, insertion, deletion, and 
                update.

  Query: Eases query URI creation by allowing URI parameters to be set as 
         dictionary attributes. For example a query with a feed of 
         '/base/feeds/snippets' and ['bq'] set to 'digital camera' will 
         produce '/base/feeds/snippets?bq=digital+camera' when .ToUri() is 
         called on it.
s   api.jscudder (Jeffrey Scudder)iN(   t   cElementTree(   t   ElementTrees   GoogleLogin auths   AuthSub tokens   https://www.google.com/t   Errorc           B   s   e  Z RS(    (   t   __name__t
   __module__(    (    (    sA   /afs/sipb.mit.edu/project/freeculture/lib/python/gdata/service.pyR   O   s   t   CaptchaRequiredc           B   s   e  Z RS(    (   R   R   (    (    (    sA   /afs/sipb.mit.edu/project/freeculture/lib/python/gdata/service.pyR   S   s   t   BadAuthenticationc           B   s   e  Z RS(    (   R   R   (    (    (    sA   /afs/sipb.mit.edu/project/freeculture/lib/python/gdata/service.pyR   W   s   t   NotAuthenticatedc           B   s   e  Z RS(    (   R   R   (    (    (    sA   /afs/sipb.mit.edu/project/freeculture/lib/python/gdata/service.pyR   [   s   t   NonAuthSubTokenc           B   s   e  Z RS(    (   R   R   (    (    (    sA   /afs/sipb.mit.edu/project/freeculture/lib/python/gdata/service.pyR   _   s   t   RequestErrorc           B   s   e  Z RS(    (   R   R   (    (    (    sA   /afs/sipb.mit.edu/project/freeculture/lib/python/gdata/service.pyR	   c   s   t   UnexpectedReturnTypec           B   s   e  Z RS(    (   R   R   (    (    (    sA   /afs/sipb.mit.edu/project/freeculture/lib/python/gdata/service.pyR
   g   s   t   GDataServicec           B   s  e  Z d  Z d% d% d d% d% d% d% d  Z d   Z d   Z d   Z d   Z e	 e e d d Z
 d	   Z d
   Z e	 e d d Z d   Z d   Z e	 e d d Z d   Z d   Z d   Z d   Z d   Z d   Z e	 e e d d Z d% d% d  Z d% d% d% d% d% d  Z e e d  Z d   Z d   Z d% d d d% d  Z d% d  Z  d% d  Z! d% d   Z" d% d% e d d% d% d!  Z# d% d% e d" d% d% d#  Z$ d% d% e d d$  Z% RS(&   s   Contains elements needed for GData login and CRUD request headers.

  Maintains additional headers (tokens for example) needed for the GData 
  services to allow a user to perform inserts, updates, and deletes.
  t   HOSTED_OR_GOOGLEc         C   s{   | |  _  | |  _ | |  _ | |  _ | |  _ | p h  |  _ |  i |  d |  _ d |  _	 d |  _
 d |  _ d |  _ d S(   s  Creates an object of type GDataService.

    Args:
      email: string (optional) The user's email address, used for
             authentication.
      password: string (optional) The user's password.
      account_type: string (optional) The type of account to use. Use
              'GOOGLE' for regular Google accounts or 'HOSTED' for Google
              Apps accounts, or 'HOSTED_OR_GOOGLE' to try finding a HOSTED
              account first and, if it doesn't exist, try finding a regular
              GOOGLE account. Default value: 'HOSTED_OR_GOOGLE'.
      service: string (optional) The desired service for which credentials
               will be obtained.
      source: string (optional) The name of the user's application.
      server: string (optional) The name of the server to which a connection
              will be opened. Default value: 'base.google.com'.
      additional_headers: dictionary (optional) Any additional headers which 
                          should be included with CRUD operations.
    N(   t   emailt   passwordt   account_typet   servicet   servert   additional_headerst   _GDataService__SetSourcet   Nonet   _GDataService__auth_tokent   _GDataService__auth_typet   _GDataService__captcha_tokent   _GDataService__captcha_urlt   _GDataService__gsessionid(   t   selfR   R   R   R   t   sourceR   R   (    (    sA   /afs/sipb.mit.edu/project/freeculture/lib/python/gdata/service.pyt   __init__r   s    									c         C   s   | |  _  t |  _ d S(   s  Sets the token sent in requests to an AuthSub token.

    Only use this method if you have received a token from the AuthSub 
    service. The auth_token is set automatically when ProgrammaticLogin()
    is used. See documentation for Google AuthSub here:
    http://code.google.com/apis/accounts/AuthForWebApps.html .

    Args:
      auth_token: string The token returned by the AuthSub service.
    N(   R   t   AUTHSUB_AUTH_LABELR   (   R   t
   auth_token(    (    sA   /afs/sipb.mit.edu/project/freeculture/lib/python/gdata/service.pyt   _SetAuthSubToken   s    	c         C   s   |  i  |  d  S(   N(   R   (   R   R   (    (    sA   /afs/sipb.mit.edu/project/freeculture/lib/python/gdata/service.pyt   __SetAuthSubToken   s    c         C   s   |  i  S(   sX   Returns the auth token used for authenticating requests.

    Returns:
      string
    (   R   (   R   (    (    sA   /afs/sipb.mit.edu/project/freeculture/lib/python/gdata/service.pyt   _GetAuthToken   s    c         C   s
   |  i    S(   N(   R!   (   R   (    (    sA   /afs/sipb.mit.edu/project/freeculture/lib/python/gdata/service.pyt   __GetAuthToken   s    t   docs-   Get or set the token used for authentication.c         C   s   |  i  S(   s   Returns a captcha token if the most recent login attempt generated one.

    The captcha token is only set if the Programmatic Login attempt failed 
    because the Google service issued a captcha challenge.

    Returns:
      string
    (   R   (   R   (    (    sA   /afs/sipb.mit.edu/project/freeculture/lib/python/gdata/service.pyt   _GetCaptchaToken   s    
c         C   s
   |  i    S(   N(   R$   (   R   (    (    sA   /afs/sipb.mit.edu/project/freeculture/lib/python/gdata/service.pyt   __GetCaptchaToken   s    s*   Get the captcha token for a login request.c         C   s   |  i  S(   s   Returns the URL of the captcha image if a login attempt generated one.
     
    The captcha URL is only set if the Programmatic Login attempt failed
    because the Google service issued a captcha challenge.

    Returns:
      string
    (   R   (   R   (    (    sA   /afs/sipb.mit.edu/project/freeculture/lib/python/gdata/service.pyt   _GetCaptchaURL   s    
c         C   s
   |  i    S(   N(   R&   (   R   (    (    sA   /afs/sipb.mit.edu/project/freeculture/lib/python/gdata/service.pyt   __GetCaptchaURL   s    s(   Get the captcha URL for a login request.c         C   s#   |  i  t j o |  i Sn d  Sd  S(   N(   R   R   R   R   (   R   (    (    sA   /afs/sipb.mit.edu/project/freeculture/lib/python/gdata/service.pyt   GetAuthSubToken   s    c         C   s   | |  _  t |  _ d  S(   N(   R   R   R   (   R   t   token(    (    sA   /afs/sipb.mit.edu/project/freeculture/lib/python/gdata/service.pyt   SetAuthSubToken   s    	c         C   s#   |  i  t j o |  i Sn d  Sd  S(   N(   R   t   PROGRAMMATIC_AUTH_LABELR   R   (   R   (    (    sA   /afs/sipb.mit.edu/project/freeculture/lib/python/gdata/service.pyt   GetClientLoginToken   s    c         C   s   | |  _  t |  _ d  S(   N(   R   R+   R   (   R   R)   (    (    sA   /afs/sipb.mit.edu/project/freeculture/lib/python/gdata/service.pyt   SetClientLoginToken   s    	c         C   s   |  i  S(   N(   t   _GDataService__source(   R   (    (    sA   /afs/sipb.mit.edu/project/freeculture/lib/python/gdata/service.pyt   __GetSource   s    c         C   s!   | |  _  d |  i  |  i d <d  S(   Ns   %s GData-Python/1.0.9s
   User-Agent(   R.   R   (   R   t
   new_source(    (    sA   /afs/sipb.mit.edu/project/freeculture/lib/python/gdata/service.pyt   __SetSource   s    	s   The source is the name of the application making the request. 
             It should be in the form company_id-app_name-app_versionc   
      C   s  | oh | oa t  i h  |  i d <|  i d <|  i d <|  i d <|  i d <| d <| d < } nL t  i h  |  i d <|  i d <|  i d <|  i d <|  i d < } |  i t  \ } } | i	 d d	  | i
 d
 d  | i
 d t t |    | i   | i |  | i   } | i d j oh | i   } xa| i   D]G } | i d  o1 | i d  |  _ t |  _ d |  _ d |  _ qWqWWn	| i d j o | i   } x | i   D]v } | i d  o
 | }	 q| i d  o | i d  |  _ q| i d  o  d t | i d  f |  _ qqW|	 d j o t d  q|	 d j o d |  _ d |  _ t d  qd |  _ d |  _ t d  n d S(   s  Authenticates the user and sets the GData Auth token.

    Login retreives a temporary auth token which must be used with all
    requests to GData services. The auth token is stored in the GData client
    object.

    Login is also used to respond to a captcha challenge. If the user's login
    attempt failed with a CaptchaRequired error, the user can respond by
    calling Login with the captcha token and the answer to the challenge.

    Args:
      captcha_token: string (optional) The identifier for the captcha challenge
                     which was presented to the user.
      captcha_response: string (optional) The user's answer to the captch 
                        challenge.

    Raises:
      CaptchaRequired if the login service will require a captcha response
      BadAuthentication if the login service rejected the username or password
      Error if the login service responded with a 403 different from the above
    t   Emailt   Passwdt   accountTypeR   R   t
   logintokent   logincaptchat   POSTs   /accounts/ClientLogins   Content-types!   application/x-www-form-urlencodeds   Content-Lengthi   s   Auth=i  s   Error=s   CaptchaToken=s   CaptchaUrl=s   %saccounts/Captcha%ss   Error=CaptchaRequireds   Captcha Requireds   Error=BadAuthentications   Incorrect username or passwords    Server responded with a 403 codeN(   t   urllibt	   urlencodeR   R   R   R   R   t   _PrepareConnectiont   AUTH_SERVER_HOSTt
   putrequestt	   putheadert   strt   lent
   endheaderst   sendt   getresponset   statust   readt
   splitlinest
   startswitht   lstripR   R+   R   R   R   R   R   R   R   (
   R   t   captcha_tokent   captcha_responset   request_bodyt   auth_connectiont   urit   auth_responset   response_bodyt   response_linet
   error_line(    (    sA   /afs/sipb.mit.edu/project/freeculture/lib/python/gdata/service.pyt   ProgrammaticLogin  sd    		
 		 
				c         C   sb   | |  _  | |  _ | o | |  _ n | o | |  _ n | o | |  _ n |  i | |  d S(   sM  Convenience method for authenticating using ProgrammaticLogin. 
    
    Sets values for email, password, and other optional members.

    Args:
      username:
      password:
      account_type: string (optional)
      service: string (optional)
      captcha_token: string (optional)
      captcha_response: string (optional)
    N(   R   R   R   R   R   RQ   (   R   t   usernameR   R   R   R   RH   RI   (    (    sA   /afs/sipb.mit.edu/project/freeculture/lib/python/gdata/service.pyt   ClientLoginb  s    		c         C   so   | o
 d } n d } | o
 d } n d } t  i h  | d <| d <| d <| d < } d t | f S(   s  Generate a URL at which the user will login and be redirected back.

    Users enter their credentials on a Google login page and a token is sent
    to the URL specified in next. See documentation for AuthSub login at:
    http://code.google.com/apis/accounts/AuthForWebApps.html

    Args:
      next: string The URL user will be sent to after logging in.
      scope: string The URL of the service to be accessed.
      secure: boolean (optional) Determines whether or not the issued token
              is a secure token.
      session: boolean (optional) Determines whether or not the issued token
               can be upgraded to a session token.
    i   i    t   nextt   scopet   securet   sessions   %saccounts/AuthSubRequest?%s(   R8   R9   R;   (   R   RT   RU   RV   RW   t   request_params(    (    sA   /afs/sipb.mit.edu/project/freeculture/lib/python/gdata/service.pyt   GenerateAuthSubURL|  s    

c         C   s   |  i  t j o
 t  n |  i t  \ } } | i d d  | i d d  | i d d |  i  |  i f  | i   | i	   } | i
   } | i d j oA x> | i   D], } | i d  o | i d  |  _ q q Wn d	 S(
   s   Upgrades a single use AuthSub token to a session token.

    Raises:
      NonAuthSubToken if the user's auth token is not an AuthSub token
    t   GETs   /accounts/AuthSubSessionTokens   Content-Types!   application/x-www-form-urlencodedt   Authorizations   %s=%si   s   Token=N(   R   R   R   R:   R;   R<   R=   R   R@   RB   RD   RC   RE   RF   RG   (   R   t   upgrade_connectionRL   t   responseRN   RO   (    (    sA   /afs/sipb.mit.edu/project/freeculture/lib/python/gdata/service.pyt   UpgradeToSessionToken  s"    
	
 c         C   s   |  i  t j o
 t  n |  i t  \ } } | i d d  | i d d  | i d d |  i  |  i f  | i   | i	   } | i
 d j o d |  _  d |  _ n d S(	   s{   Revokes an existing AuthSub token.

    Raises:
      NonAuthSubToken if the user's auth token is not an AuthSub token
    RZ   s   /accounts/AuthSubRevokeTokens   Content-Types!   application/x-www-form-urlencodedR[   s   %s=%si   N(   R   R   R   R:   R;   R<   R=   R   R@   RB   RC   R   (   R   t   revoke_connectionRL   R]   (    (    sA   /afs/sipb.mit.edu/project/freeculture/lib/python/gdata/service.pyt   RevokeAuthSubToken  s    
	
	i   s   UTF-8c         C   s^  | d j o
 h  } n |  i o d |  i |  i f | d <n |  i d j	 o` | i d  d j  oF | i d  d j o | d |  i f 7} q | d |  i f 7} q n t i i i |  | |  } | i	   } | i
 d	 j oY | o | |  Sn t i |  } | p& t i |  }	 |	 p | Sn |	 Sn | Sn| i
 d
 j o | d j o | i d  }
 |
 d j	 ob t i d  i |
  } | d j	 o | i d  |  _ n |  i |
 | | d d | d | Sq,t h  | i
 d <d d <| d < qZt h  | i
 d <d d <| d < n+ t h  | i
 d <| i d <| d < d S(   sR  Query the GData API with the given URI

    The uri is the portion of the URI after the server value 
    (ex: www.google.com).

    To perform a query against Google Base, set the server to 
    'base.google.com' and set the uri to '/base/feeds/...', where ... is 
    your query. For example, to find snippets for all digital cameras uri 
    should be set to: '/base/feeds/snippets?bq=digital+camera'

    Args:
      uri: string The query in the form of a URI. Example:
           '/base/feeds/snippets?bq=digital+camera'.
      extra_headers: dictionary (optional) Extra HTTP headers to be included
                     in the GET request. These headers are in addition to 
                     those stored in the client's additional_headers property.
                     The client automatically sets the Content-Type and 
                     Authorization headers.
      redirects_remaining: int (optional) Tracks the number of additional
          redirects this method will allow. If the service object receives
          a redirect and remaining is 0, it will not follow the redirect. 
          This was added to avoid infinite redirect loops.
      encoding: string (optional) The character encoding for the server's
          response. Default is UTF-8
      converter: func (optional) A function which will transform
          the server's results before it is returned. Example: use 
          GDataFeedFromString to parse the server response as if it
          were a GDataFeed.

    Returns:
      If there is no ResultsTransformer specified in the call, a GDataFeed 
      or GDataEntry depending on which is sent from the server. If the 
      response is niether a feed or entry and there is no ResultsTransformer,
      return a string. If there is a ResultsTransformer, the returned value 
      will be that of the ResultsTransformer function.
    s   %s=%sR[   s   gsessionid=i    t   ?is   &gsessionid=%ss   ?gsessionid=%si   i.  t   Locations   [\?\&]gsessionid=(\w*)i   t   encodingt	   converterRC   s$   302 received without Location headert   reasont   bodys/   Redirect received, but redirects_remaining <= 0N(   R   R   R   R   t   findt   atomR   t   AtomServicet   GetRD   RC   t   gdatat   GDataFeedFromStringt   GDataEntryFromStringt	   getheadert   ret   compilet   searcht   groupR	   Re   (   R   RL   t   extra_headerst   redirects_remainingRc   Rd   t   server_responset   result_bodyt   feedt   entryt   locationt   m(    (    sA   /afs/sipb.mit.edu/project/freeculture/lib/python/gdata/service.pyRj     sN    &

			c         C   sO   t  i i i |  | d |  } | i   } t i | | i d  | i d   S(   s[   Returns a MediaSource containing media and its metadata from the given
    URI string.
    RZ   s   Content-Types   Content-Length(   Rh   R   Ri   t   _CreateConnectionRB   Rk   t   MediaSourceRn   (   R   RL   Rs   t
   connectiont   response_handle(    (    sA   /afs/sipb.mit.edu/project/freeculture/lib/python/gdata/service.pyt   GetMedia/  s
    	c         C   sC   |  i  | | d t i } t | t i  o | Sn
 t d  d S(   s  Query the GData API with the given URI and receive an Entry.
    
    See also documentation for gdata.service.Get

    Args:
      uri: string The query in the form of a URI. Example:
           '/base/feeds/snippets?bq=digital+camera'.
      extra_headers: dictionary (optional) Extra HTTP headers to be included
                     in the GET request. These headers are in addition to
                     those stored in the client's additional_headers property.
                     The client automatically sets the Content-Type and
                     Authorization headers.

    Returns:
      A GDataEntry built from the XML in the server's response.
    Rd   s   Server did not send an entryN(   Rj   Rh   t   EntryFromStringt
   isinstancet   EntryR
   (   R   RL   Rs   t   result(    (    sA   /afs/sipb.mit.edu/project/freeculture/lib/python/gdata/service.pyt   GetEntry9  s    c         C   sC   |  i  | | d t i } t | t i  o | Sn
 t d  d S(   s  Query the GData API with the given URI and receive a Feed.

    See also documentation for gdata.service.Get

    Args:
      uri: string The query in the form of a URI. Example:
           '/base/feeds/snippets?bq=digital+camera'.
      extra_headers: dictionary (optional) Extra HTTP headers to be included
                     in the GET request. These headers are in addition to
                     those stored in the client's additional_headers property.
                     The client automatically sets the Content-Type and
                     Authorization headers.

    Returns:
      A GDataFeed built from the XML in the server's response.
    Rd   s   Server did not send a feedN(   Rj   Rh   t   FeedFromStringR   t   FeedR
   (   R   RL   Rs   R   (    (    sA   /afs/sipb.mit.edu/project/freeculture/lib/python/gdata/service.pyt   GetFeedQ  s    c	      
   C   s  | d$ j o
 h  } n |  i o d |  i |  i f | d <n |  i d$ j	 o` | i d  d j  oF | i d  d j o | d |  i f 7} q | d |  i f 7} q n | o| o}t i |  o t i |  }	 n t |  }	 g  }
 |
 i	 d	 d
  |
 i	 d | i
 d  |
 i	 d  d | d <d | d <t t |
 d  t |
 d  t |
 d  t |	  | i  | d <t i i i |  | d | | |  } | i |
 d  | i |	  | i |
 d  x4 | i i d  } | d j o Pn | i |  q| i |
 d  | i   } | i   } n | o | i
 | d <| i | d <t i i i |  | d | | |  } x4 | i i d  } | d j o Pn | i |  q| i   } | i   } n@ | } d } t i i i |  | | | | | |  } | i   } | i d j p | i d j oY | o | |  Sn t i |  } | p& t i |  } | p | Sn | Sn | Sn"| i d j o | d j o | i d  } | d$ j	 oh t i d  i |  } | d$ j	 o | i d  |  _ n |  i | | | | | | d | d | Sq}t h  | i d <d  d! <| d" < qt h  | i d <d# d! <| d" < n+ t h  | i d <| i  d! <| d" < d$ S(%   s  Insert data into a GData service at the given URI.

    Args:
      data: string, ElementTree._Element, atom.Entry, or gdata.GDataEntry The
            XML to be sent to the uri. 
      uri: string The location (feed) to which the data should be inserted. 
           Example: '/base/feeds/items'. 
      extra_headers: dict (optional) HTTP headers which are to be included. 
                     The client automatically sets the Content-Type,
                     Authorization, and Content-Length headers.
      url_params: dict (optional) Additional URL parameters to be included
                  in the URI. These are translated into query arguments
                  in the form '&dict_key=value&...'.
                  Example: {'max-results': '250'} becomes &max-results=250
      escape_params: boolean (optional) If false, the calling code has already
                     ensured that the query will form a valid URL (all
                     reserved characters have been escaped). If true, this
                     method will escape the query and any URL parameters
                     provided.
      media_source: MediaSource (optional) Container for the media to be sent
          along with the entry, if provided.
      converter: func (optional) A function which will be executed on the 
          server's response. Often this is a function like 
          GDataEntryFromString which will parse the body of the server's 
          response and return a GDataEntry.

    Returns:
      If the post succeeded, this method will return a GDataFeed, GDataEntry,
      or the results of running converter on the server's result body (if
      converter was specified).
    s   %s=%sR[   s   gsessionid=i    Ra   is   &gsessionid=%ss   ?gsessionid=%ss(   Media multipart posting
--END_OF_PART
s&   Content-Type: application/atom+xml

s   
--END_OF_PART
Content-Type: s   

s   
--END_OF_PART--
s'   multipart/related; boundary=END_OF_PARTs   Content-Types   1.0s   MIME-versioni   i   s   Content-LengthR7   i t    s   application/atom+xmli   i   i.  Rb   s   [\?\&]gsessionid=(\w*)Rd   RC   s$   302 received without Location headerRe   Rf   s/   Redirect received, but redirects_remaining <= 0N(!   R   R   R   R   Rg   R   t	   iselementt   tostringR>   t   appendt   content_typeR?   t   content_lengthRh   R   Ri   R{   RA   t   file_handleRD   RB   t   PostRC   Rk   Rl   Rm   Rn   Ro   Rp   Rq   Rr   R	   Re   (   R   t   dataRL   Rs   t
   url_paramst   escape_paramsRt   t   media_sourceRd   t   data_strt	   multipartt   insert_connectiont
   binarydataRu   Rv   t	   http_dataR   Rw   Rx   Ry   Rz   (    (    sA   /afs/sipb.mit.edu/project/freeculture/lib/python/gdata/service.pyR   i  s    "

		

D 		i   c	         C   s  | d$ j o
 h  } n |  i o d |  i |  i f | d <n |  i d$ j	 o` | i d  d j  oF | i d  d j o | d |  i f 7} q | d |  i f 7} q n | o| o}t i |  o t i |  }	 n t |  }	 g  }
 |
 i	 d	 d
  |
 i	 d | i
 d  |
 i	 d  d | d <d | d <t t |
 d  t |
 d  t |
 d  t |	  | i  | d <t i i i |  | d | | |  } | i |
 d  | i |	  | i |
 d  x4 | i i d  } | d j o Pn | i |  q| i |
 d  | i   } | i   } n | o | i
 | d <| i | d <t i i i |  | d | | |  } x4 | i i d  } | d j o Pn | i |  q| i   } | i   } n@ | } d } t i i i |  | | | | | |  } | i   } | i d j oY | o | |  Sn t i |  } | p& t i |  } | p | Sn | Sn | Sn%| i d j o | d j o | i d  } | d$ j	 ok t i d  i |  } | d$ j	 o | i d  |  _ n |  i | | | | | | d d | d | Sqpt h  | i d <d  d! <| d" < qt h  | i d <d# d! <| d" < n+ t h  | i d <| i  d! <| d" < d$ S(%   s  Updates an entry at the given URI.
     
    Args:
      data: string, ElementTree._Element, or xml_wrapper.ElementWrapper The 
            XML containing the updated data.
      uri: string A URI indicating entry to which the update will be applied.
           Example: '/base/feeds/items/ITEM-ID'
      extra_headers: dict (optional) HTTP headers which are to be included.
                     The client automatically sets the Content-Type,
                     Authorization, and Content-Length headers.
      url_params: dict (optional) Additional URL parameters to be included
                  in the URI. These are translated into query arguments
                  in the form '&dict_key=value&...'.
                  Example: {'max-results': '250'} becomes &max-results=250
      escape_params: boolean (optional) If false, the calling code has already
                     ensured that the query will form a valid URL (all
                     reserved characters have been escaped). If true, this
                     method will escape the query and any URL parameters
                     provided.
      converter: func (optional) A function which will be executed on the 
          server's response. Often this is a function like 
          GDataEntryFromString which will parse the body of the server's 
          response and return a GDataEntry.

    Returns:
      If the put succeeded, this method will return a GDataFeed, GDataEntry,
      or the results of running converter on the server's result body (if
      converter was specified).
    s   %s=%sR[   s   gsessionid=i    Ra   is   &gsessionid=%ss   ?gsessionid=%ss(   Media multipart posting
--END_OF_PART
s&   Content-Type: application/atom+xml

s   
--END_OF_PART
Content-Type: s   

s   
--END_OF_PART--
s'   multipart/related; boundary=END_OF_PARTs   Content-Types   1.0s   MIME-versioni   i   s   Content-Lengtht   PUTi R   s   application/atom+xmli   i.  Rb   s   [\?\&]gsessionid=(\w*)R   Rd   RC   s$   302 received without Location headerRe   Rf   s/   Redirect received, but redirects_remaining <= 0N(!   R   R   R   R   Rg   R   R   R   R>   R   R   R?   R   Rh   R   Ri   R{   RA   R   RD   RB   t   PutRC   Rk   Rl   Rm   Rn   Ro   Rp   Rq   Rr   R	   Re   (   R   R   RL   Rs   R   R   Rt   R   Rd   R   R   R   R   Ru   Rv   R   R   Rw   Rx   Ry   Rz   (    (    sA   /afs/sipb.mit.edu/project/freeculture/lib/python/gdata/service.pyR     s     

		

D		c   
      C   s  | d j o
 h  } n |  i o d |  i |  i f | d <n |  i d j	 o` | i d  d j  oF | i d  d j o | d |  i f 7} q | d |  i f 7} q n t i i i |  | | | |  } | i	   } | i
 d	 j o t Sn| i
 d
 j o | d j o | i d  } | d j	 o\ t i d  i |  }	 |	 d j	 o |	 i d  |  _ n |  i | | | | | d  Sqt h  | i
 d <d d <| d < q	t h  | i
 d <d d <| d < n+ t h  | i
 d <| i d <| d < d S(   s  Deletes the entry at the given URI.

    Args:
      uri: string The URI of the entry to be deleted. Example: 
           '/base/feeds/items/ITEM-ID'
      extra_headers: dict (optional) HTTP headers which are to be included.
                     The client automatically sets the Content-Type and
                     Authorization headers.
      url_params: dict (optional) Additional URL parameters to be included
                  in the URI. These are translated into query arguments
                  in the form '&dict_key=value&...'.
                  Example: {'max-results': '250'} becomes &max-results=250
      escape_params: boolean (optional) If false, the calling code has already
                     ensured that the query will form a valid URL (all
                     reserved characters have been escaped). If true, this
                     method will escape the query and any URL parameters
                     provided.

    Returns:
      True if the entry was deleted.
    s   %s=%sR[   s   gsessionid=i    Ra   is   &gsessionid=%ss   ?gsessionid=%si   i.  Rb   s   [\?\&]gsessionid=(\w*)i   RC   s$   302 received without Location headerRe   Rf   s/   Redirect received, but redirects_remaining <= 0N(   R   R   R   R   Rg   Rh   R   Ri   t   DeleteRD   RC   t   TrueRn   Ro   Rp   Rq   Rr   R	   Re   (
   R   RL   Rs   R   R   Rt   Ru   Rv   Ry   Rz   (    (    sA   /afs/sipb.mit.edu/project/freeculture/lib/python/gdata/service.pyR     s@    

			N(&   R   R   t   __doc__R   R   R   t   _GDataService__SetAuthSubTokenR!   t   _GDataService__GetAuthTokent   propertyR   R$   t   _GDataService__GetCaptchaTokenRH   R&   t   _GDataService__GetCaptchaURLt   captcha_urlR(   R*   R,   R-   t   _GDataService__GetSourceR   R   RQ   RS   t   FalseR   RY   R^   R`   Rj   R   R   R   R   R   R   (    (    (    sA   /afs/sipb.mit.edu/project/freeculture/lib/python/gdata/service.pyR   k   sX   		#																					a 		]
		t   Queryc           B   s  e  Z d  Z d d d d d  Z d   Z d   Z e e e d d Z d   Z	 d   Z
 e e	 e
 d d Z d	   Z d
   Z e e e d d Z d   Z d   Z e e e d d Z d   Z d   Z e e e d d Z d   Z d   Z e e e d d Z d   Z d   Z e e e d d Z d   Z d   Z e e e d d Z d   Z d   Z e e e d d Z  d   Z! RS(    s  Constructs a query URL to be used in GET requests
  
  Url parameters are created by adding key-value pairs to this object as a 
  dict. For example, to add &max-results=25 to the URL do
  my_query['max-results'] = 25

  Category queries are created by adding category strings to the categories
  member. All items in the categories list will be concatenated with the /
  symbol (symbolizing a category x AND y restriction). If you would like to OR
  2 categories, append them as one string with a | between the categories. 
  For example, do query.categories.append('Fritz|Laurie') to create a query
  like this feed/-/Fritz%7CLaurie . This query will look for results in both
  categories.
  c         C   s   | |  _  g  |  _ | o | |  _ n t | t  o# x  | D] } | | |  | <q= Wn t | t  o% x" | D] } |  i i |  qp Wn d S(   sX  Constructor for Query
    
    Args:
      feed: str (optional) The path for the feed (Examples: 
          '/base/feeds/snippets' or 'calendar/feeds/jo@gmail.com/private/full'
      text_query: str (optional) The contents of the q query parameter. The
          contents of the text_query are URL escaped upon conversion to a URI.
      params: dict (optional) Parameter value string pairs which become URL
          params when translated to a URI. These parameters are added to the
          query's items (key-value pairs).
      categories: list (optional) List of category strings which should be
          included as query categories. See 
          http://code.google.com/apis/gdata/reference.html#Queries for 
          details. If you want to get results from category A or B (both 
          categories), specify a single list item 'A|B'. 
    N(   Rw   t
   categoriest
   text_queryR   t   dictt   listR   (   R   Rw   R   t   paramsR   t   paramt   category(    (    sA   /afs/sipb.mit.edu/project/freeculture/lib/python/gdata/service.pyR     s    		  c         C   s'   d |  i    j o |  d Sn d  Sd  S(   Nt   q(   t   keysR   (   R   (    (    sA   /afs/sipb.mit.edu/project/freeculture/lib/python/gdata/service.pyt   _GetTextQuery  s    c         C   s   | |  d <d  S(   NR   (    (   R   t   query(    (    sA   /afs/sipb.mit.edu/project/freeculture/lib/python/gdata/service.pyt   _SetTextQuery  s    R#   s   The feed query's q parameterc         C   s'   d |  i    j o |  d Sn d  Sd  S(   Nt   author(   R   R   (   R   (    (    sA   /afs/sipb.mit.edu/project/freeculture/lib/python/gdata/service.pyt
   _GetAuthor  s    c         C   s   | |  d <d  S(   NR   (    (   R   R   (    (    sA   /afs/sipb.mit.edu/project/freeculture/lib/python/gdata/service.pyt
   _SetAuthor  s    s!   The feed query's author parameterc         C   s'   d |  i    j o |  d Sn d  Sd  S(   Nt   alt(   R   R   (   R   (    (    sA   /afs/sipb.mit.edu/project/freeculture/lib/python/gdata/service.pyt   _GetAlt  s    c         C   s   | |  d <d  S(   NR   (    (   R   R   (    (    sA   /afs/sipb.mit.edu/project/freeculture/lib/python/gdata/service.pyt   _SetAlt  s    s   The feed query's alt parameterc         C   s'   d |  i    j o |  d Sn d  Sd  S(   Ns   updated-min(   R   R   (   R   (    (    sA   /afs/sipb.mit.edu/project/freeculture/lib/python/gdata/service.pyt   _GetUpdatedMin  s    c         C   s   | |  d <d  S(   Ns   updated-min(    (   R   R   (    (    sA   /afs/sipb.mit.edu/project/freeculture/lib/python/gdata/service.pyt   _SetUpdatedMin  s    s&   The feed query's updated-min parameterc         C   s'   d |  i    j o |  d Sn d  Sd  S(   Ns   updated-max(   R   R   (   R   (    (    sA   /afs/sipb.mit.edu/project/freeculture/lib/python/gdata/service.pyt   _GetUpdatedMax  s    c         C   s   | |  d <d  S(   Ns   updated-max(    (   R   R   (    (    sA   /afs/sipb.mit.edu/project/freeculture/lib/python/gdata/service.pyt   _SetUpdatedMax%  s    s&   The feed query's updated-max parameterc         C   s'   d |  i    j o |  d Sn d  Sd  S(   Ns   published-min(   R   R   (   R   (    (    sA   /afs/sipb.mit.edu/project/freeculture/lib/python/gdata/service.pyt   _GetPublishedMin+  s    c         C   s   | |  d <d  S(   Ns   published-min(    (   R   R   (    (    sA   /afs/sipb.mit.edu/project/freeculture/lib/python/gdata/service.pyt   _SetPublishedMin1  s    s(   The feed query's published-min parameterc         C   s'   d |  i    j o |  d Sn d  Sd  S(   Ns   published-max(   R   R   (   R   (    (    sA   /afs/sipb.mit.edu/project/freeculture/lib/python/gdata/service.pyt   _GetPublishedMax7  s    c         C   s   | |  d <d  S(   Ns   published-max(    (   R   R   (    (    sA   /afs/sipb.mit.edu/project/freeculture/lib/python/gdata/service.pyt   _SetPublishedMax=  s    s(   The feed query's published-max parameterc         C   s'   d |  i    j o |  d Sn d  Sd  S(   Ns   start-index(   R   R   (   R   (    (    sA   /afs/sipb.mit.edu/project/freeculture/lib/python/gdata/service.pyt   _GetStartIndexC  s    c         C   s   | |  d <d  S(   Ns   start-index(    (   R   R   (    (    sA   /afs/sipb.mit.edu/project/freeculture/lib/python/gdata/service.pyt   _SetStartIndexI  s    s&   The feed query's start-index parameterc         C   s'   d |  i    j o |  d Sn d  Sd  S(   Ns   max-results(   R   R   (   R   (    (    sA   /afs/sipb.mit.edu/project/freeculture/lib/python/gdata/service.pyt   _GetMaxResultsO  s    c         C   s   | |  d <d  S(   Ns   max-results(    (   R   R   (    (    sA   /afs/sipb.mit.edu/project/freeculture/lib/python/gdata/service.pyt   _SetMaxResultsU  s    s&   The feed query's max-results parameterc         C   s   |  i  p d } d i g  } |  i D] } | t i |  q$ ~  } t |  i  d j o | d | } n t i i | |   S(   NR   t   /i    s   /-/(	   Rw   t   joinR   R8   t
   quote_plusR?   Rh   R   t   BuildUri(   R   t   q_feedt   _[1]t   ct   category_string(    (    sA   /afs/sipb.mit.edu/project/freeculture/lib/python/gdata/service.pyt   ToUri\  s    0N("   R   R   R   R   R   R   R   R   R   R   R   R   R   R   R   R   R   t   updated_minR   R   t   updated_maxR   R   t   published_minR   R   t   published_maxR   R   t   start_indexR   R   t   max_resultsR   (    (    (    sA   /afs/sipb.mit.edu/project/freeculture/lib/python/gdata/service.pyR     sP   																												(   R   t
   __author__Ro   t   httplibR8   t	   xml.etreeR    R   t   ImportErrort   elementtreet   atom.serviceRh   Rk   R+   R   R;   t	   ExceptionR   R   R   R   R   R	   R
   R   Ri   R   R   R   (    (    (    sA   /afs/sipb.mit.edu/project/freeculture/lib/python/gdata/service.pys   <module>6   s:      Y