home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / var / lib / python-support / python2.6 / atom / service.pyc (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2009-04-20  |  25.7 KB  |  705 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. '''AtomService provides CRUD ops. in line with the Atom Publishing Protocol.
  5.  
  6.   AtomService: Encapsulates the ability to perform insert, update and delete
  7.                operations with the Atom Publishing Protocol on which GData is
  8.                based. An instance can perform query, insertion, deletion, and
  9.                update.
  10.  
  11.   HttpRequest: Function that performs a GET, POST, PUT, or DELETE HTTP request
  12.        to the specified end point. An AtomService object or a subclass can be
  13.        used to specify information about the request.
  14. '''
  15. __author__ = 'api.jscudder (Jeff Scudder)'
  16. import atom.http_interface as atom
  17. import atom.url as atom
  18. import atom.http as atom
  19. import atom.token_store as atom
  20. import os
  21. import httplib
  22. import urllib
  23. import re
  24. import base64
  25. import socket
  26. import warnings
  27.  
  28. try:
  29.     from xml.etree import cElementTree as ElementTree
  30. except ImportError:
  31.     
  32.     try:
  33.         import cElementTree as ElementTree
  34.     except ImportError:
  35.         
  36.         try:
  37.             from xml.etree import ElementTree
  38.         except ImportError:
  39.             from elementtree import ElementTree
  40.         except:
  41.             None<EXCEPTION MATCH>ImportError
  42.         
  43.  
  44.         None<EXCEPTION MATCH>ImportError
  45.     
  46.  
  47.     None<EXCEPTION MATCH>ImportError
  48.  
  49.  
  50. class AtomService(object):
  51.     '''Performs Atom Publishing Protocol CRUD operations.
  52.   
  53.   The AtomService contains methods to perform HTTP CRUD operations. 
  54.   '''
  55.     port = 80
  56.     ssl = False
  57.     current_token = None
  58.     auto_store_tokens = True
  59.     auto_set_current_token = True
  60.     
  61.     def _get_override_token(self):
  62.         return self.current_token
  63.  
  64.     
  65.     def _set_override_token(self, token):
  66.         self.current_token = token
  67.  
  68.     override_token = property(_get_override_token, _set_override_token)
  69.     
  70.     def __init__(self, server = None, additional_headers = None, application_name = '', http_client = None, token_store = None):
  71.         """Creates a new AtomService client.
  72.     
  73.     Args:
  74.       server: string (optional) The start of a URL for the server
  75.               to which all operations should be directed. Example: 
  76.               'www.google.com'
  77.       additional_headers: dict (optional) Any additional HTTP headers which
  78.                           should be included with CRUD operations.
  79.       http_client: An object responsible for making HTTP requests using a
  80.                    request method. If none is provided, a new instance of
  81.                    atom.http.ProxiedHttpClient will be used.
  82.       token_store: Keeps a collection of authorization tokens which can be
  83.                    applied to requests for a specific URLs. Critical methods are
  84.                    find_token based on a URL (atom.url.Url or a string), add_token,
  85.                    and remove_token.
  86.     """
  87.         if not http_client:
  88.             pass
  89.         self.http_client = atom.http.ProxiedHttpClient()
  90.         if not token_store:
  91.             pass
  92.         self.token_store = atom.token_store.TokenStore()
  93.         self.server = server
  94.         if not additional_headers:
  95.             pass
  96.         self.additional_headers = { }
  97.         self.additional_headers['User-Agent'] = atom.http_interface.USER_AGENT % (application_name,)
  98.         self._set_debug(False)
  99.  
  100.     
  101.     def _get_debug(self):
  102.         return self.http_client.debug
  103.  
  104.     
  105.     def _set_debug(self, value):
  106.         self.http_client.debug = value
  107.  
  108.     debug = property(_get_debug, _set_debug, doc = 'If True, HTTP debug information is printed.')
  109.     
  110.     def use_basic_auth(self, username, password, scopes = None):
  111.         if username is not None and password is not None:
  112.             if scopes is None:
  113.                 scopes = [
  114.                     atom.token_store.SCOPE_ALL]
  115.             
  116.             base_64_string = base64.encodestring('%s:%s' % (username, password))
  117.             token = BasicAuthToken('Basic %s' % base_64_string.strip(), scopes = [
  118.                 atom.token_store.SCOPE_ALL])
  119.             if self.auto_set_current_token:
  120.                 self.current_token = token
  121.             
  122.             if self.auto_store_tokens:
  123.                 return self.token_store.add_token(token)
  124.             return True
  125.         return False
  126.  
  127.     
  128.     def UseBasicAuth(self, username, password, for_proxy = False):
  129.         '''Sets an Authenticaiton: Basic HTTP header containing plaintext.
  130.  
  131.     Deprecated, use use_basic_auth instead.
  132.     
  133.     The username and password are base64 encoded and added to an HTTP header
  134.     which will be included in each request. Note that your username and 
  135.     password are sent in plaintext.
  136.  
  137.     Args:
  138.       username: str
  139.       password: str
  140.     '''
  141.         self.use_basic_auth(username, password)
  142.  
  143.     
  144.     def request(self, operation, url, data = None, headers = None, url_params = None):
  145.         if isinstance(url, str):
  146.             if not url.startswith('http') and self.ssl:
  147.                 url = atom.url.parse_url('https://%s%s' % (self.server, url))
  148.             elif not url.startswith('http'):
  149.                 url = atom.url.parse_url('http://%s%s' % (self.server, url))
  150.             else:
  151.                 url = atom.url.parse_url(url)
  152.         
  153.         if url_params:
  154.             for name, value in url_params.iteritems():
  155.                 url.params[name] = value
  156.             
  157.         
  158.         all_headers = self.additional_headers.copy()
  159.         if headers:
  160.             all_headers.update(headers)
  161.         
  162.         if data and 'Content-Length' not in all_headers:
  163.             content_length = CalculateDataLength(data)
  164.             if content_length:
  165.                 all_headers['Content-Length'] = str(content_length)
  166.             
  167.         
  168.         if self.override_token:
  169.             auth_token = self.override_token
  170.         else:
  171.             auth_token = self.token_store.find_token(url)
  172.         return auth_token.perform_request(self.http_client, operation, url, data = data, headers = all_headers)
  173.  
  174.     
  175.     def Get(self, uri, extra_headers = None, url_params = None, escape_params = True):
  176.         """Query the APP server with the given URI
  177.  
  178.     The uri is the portion of the URI after the server value 
  179.     (server example: 'www.google.com').
  180.  
  181.     Example use:
  182.     To perform a query against Google Base, set the server to 
  183.     'base.google.com' and set the uri to '/base/feeds/...', where ... is 
  184.     your query. For example, to find snippets for all digital cameras uri 
  185.     should be set to: '/base/feeds/snippets?bq=digital+camera'
  186.  
  187.     Args:
  188.       uri: string The query in the form of a URI. Example:
  189.            '/base/feeds/snippets?bq=digital+camera'.
  190.       extra_headers: dicty (optional) Extra HTTP headers to be included
  191.                      in the GET request. These headers are in addition to 
  192.                      those stored in the client's additional_headers property.
  193.                      The client automatically sets the Content-Type and 
  194.                      Authorization headers.
  195.       url_params: dict (optional) Additional URL parameters to be included
  196.                   in the query. These are translated into query arguments
  197.                   in the form '&dict_key=value&...'.
  198.                   Example: {'max-results': '250'} becomes &max-results=250
  199.       escape_params: boolean (optional) If false, the calling code has already
  200.                      ensured that the query will form a valid URL (all
  201.                      reserved characters have been escaped). If true, this
  202.                      method will escape the query and any URL parameters
  203.                      provided.
  204.  
  205.     Returns:
  206.       httplib.HTTPResponse The server's response to the GET request.
  207.     """
  208.         return self.request('GET', uri, data = None, headers = extra_headers, url_params = url_params)
  209.  
  210.     
  211.     def Post(self, data, uri, extra_headers = None, url_params = None, escape_params = True, content_type = 'application/atom+xml'):
  212.         """Insert data into an APP server at the given URI.
  213.  
  214.     Args:
  215.       data: string, ElementTree._Element, or something with a __str__ method 
  216.             The XML to be sent to the uri. 
  217.       uri: string The location (feed) to which the data should be inserted. 
  218.            Example: '/base/feeds/items'. 
  219.       extra_headers: dict (optional) HTTP headers which are to be included. 
  220.                      The client automatically sets the Content-Type,
  221.                      Authorization, and Content-Length headers.
  222.       url_params: dict (optional) Additional URL parameters to be included
  223.                   in the URI. These are translated into query arguments
  224.                   in the form '&dict_key=value&...'.
  225.                   Example: {'max-results': '250'} becomes &max-results=250
  226.       escape_params: boolean (optional) If false, the calling code has already
  227.                      ensured that the query will form a valid URL (all
  228.                      reserved characters have been escaped). If true, this
  229.                      method will escape the query and any URL parameters
  230.                      provided.
  231.  
  232.     Returns:
  233.       httplib.HTTPResponse Server's response to the POST request.
  234.     """
  235.         if extra_headers is None:
  236.             extra_headers = { }
  237.         
  238.         if content_type:
  239.             extra_headers['Content-Type'] = content_type
  240.         
  241.         return self.request('POST', uri, data = data, headers = extra_headers, url_params = url_params)
  242.  
  243.     
  244.     def Put(self, data, uri, extra_headers = None, url_params = None, escape_params = True, content_type = 'application/atom+xml'):
  245.         """Updates an entry at the given URI.
  246.      
  247.     Args:
  248.       data: string, ElementTree._Element, or xml_wrapper.ElementWrapper The 
  249.             XML containing the updated data.
  250.       uri: string A URI indicating entry to which the update will be applied.
  251.            Example: '/base/feeds/items/ITEM-ID'
  252.       extra_headers: dict (optional) HTTP headers which are to be included.
  253.                      The client automatically sets the Content-Type,
  254.                      Authorization, and Content-Length headers.
  255.       url_params: dict (optional) Additional URL parameters to be included
  256.                   in the URI. These are translated into query arguments
  257.                   in the form '&dict_key=value&...'.
  258.                   Example: {'max-results': '250'} becomes &max-results=250
  259.       escape_params: boolean (optional) If false, the calling code has already
  260.                      ensured that the query will form a valid URL (all
  261.                      reserved characters have been escaped). If true, this
  262.                      method will escape the query and any URL parameters
  263.                      provided.
  264.   
  265.     Returns:
  266.       httplib.HTTPResponse Server's response to the PUT request.
  267.     """
  268.         if extra_headers is None:
  269.             extra_headers = { }
  270.         
  271.         if content_type:
  272.             extra_headers['Content-Type'] = content_type
  273.         
  274.         return self.request('PUT', uri, data = data, headers = extra_headers, url_params = url_params)
  275.  
  276.     
  277.     def Delete(self, uri, extra_headers = None, url_params = None, escape_params = True):
  278.         """Deletes the entry at the given URI.
  279.  
  280.     Args:
  281.       uri: string The URI of the entry to be deleted. Example: 
  282.            '/base/feeds/items/ITEM-ID'
  283.       extra_headers: dict (optional) HTTP headers which are to be included.
  284.                      The client automatically sets the Content-Type and
  285.                      Authorization headers.
  286.       url_params: dict (optional) Additional URL parameters to be included
  287.                   in the URI. These are translated into query arguments
  288.                   in the form '&dict_key=value&...'.
  289.                   Example: {'max-results': '250'} becomes &max-results=250
  290.       escape_params: boolean (optional) If false, the calling code has already
  291.                      ensured that the query will form a valid URL (all
  292.                      reserved characters have been escaped). If true, this
  293.                      method will escape the query and any URL parameters
  294.                      provided.
  295.  
  296.     Returns:
  297.       httplib.HTTPResponse Server's response to the DELETE request.
  298.     """
  299.         return self.request('DELETE', uri, data = None, headers = extra_headers, url_params = url_params)
  300.  
  301.  
  302.  
  303. class BasicAuthToken(atom.http_interface.GenericToken):
  304.     
  305.     def __init__(self, auth_header, scopes = None):
  306.         """Creates a token used to add Basic Auth headers to HTTP requests.
  307.  
  308.     Args:
  309.       auth_header: str The value for the Authorization header.
  310.       scopes: list of str or atom.url.Url specifying the beginnings of URLs
  311.           for which this token can be used. For example, if scopes contains
  312.           'http://example.com/foo', then this token can be used for a request to
  313.           'http://example.com/foo/bar' but it cannot be used for a request to
  314.           'http://example.com/baz'
  315.     """
  316.         self.auth_header = auth_header
  317.         if not scopes:
  318.             pass
  319.         self.scopes = []
  320.  
  321.     
  322.     def perform_request(self, http_client, operation, url, data = None, headers = None):
  323.         '''Sets the Authorization header to the basic auth string.'''
  324.         if headers is None:
  325.             headers = {
  326.                 'Authorization': self.auth_header }
  327.         else:
  328.             headers['Authorization'] = self.auth_header
  329.         return http_client.request(operation, url, data = data, headers = headers)
  330.  
  331.     
  332.     def __str__(self):
  333.         return self.auth_header
  334.  
  335.     
  336.     def valid_for_scope(self, url):
  337.         '''Tells the caller if the token authorizes access to the desired URL.
  338.     '''
  339.         if isinstance(url, (str, unicode)):
  340.             url = atom.url.parse_url(url)
  341.         
  342.         for scope in self.scopes:
  343.             if scope == atom.token_store.SCOPE_ALL:
  344.                 return True
  345.             if isinstance(scope, (str, unicode)):
  346.                 scope = atom.url.parse_url(scope)
  347.             
  348.             if scope == url:
  349.                 return True
  350.             if scope.host == url.host and not (scope.path):
  351.                 return True
  352.             if scope.host == url.host and scope.path and not (url.path):
  353.                 continue
  354.                 continue
  355.             not (scope.path)
  356.             if scope.host == url.host and url.path.startswith(scope.path):
  357.                 return True
  358.         
  359.         return False
  360.  
  361.  
  362.  
  363. def PrepareConnection(service, full_uri):
  364.     """Opens a connection to the server based on the full URI.
  365.  
  366.   This method is deprecated, instead use atom.http.HttpClient.request.
  367.  
  368.   Examines the target URI and the proxy settings, which are set as
  369.   environment variables, to open a connection with the server. This
  370.   connection is used to make an HTTP request.
  371.  
  372.   Args:
  373.     service: atom.AtomService or a subclass. It must have a server string which
  374.       represents the server host to which the request should be made. It may also
  375.       have a dictionary of additional_headers to send in the HTTP request.
  376.     full_uri: str Which is the target relative (lacks protocol and host) or
  377.     absolute URL to be opened. Example:
  378.     'https://www.google.com/accounts/ClientLogin' or
  379.     'base/feeds/snippets' where the server is set to www.google.com.
  380.  
  381.   Returns:
  382.     A tuple containing the httplib.HTTPConnection and the full_uri for the
  383.     request.
  384.   """
  385.     deprecation('calling deprecated function PrepareConnection')
  386.     (server, port, ssl, partial_uri) = ProcessUrl(service, full_uri)
  387.     if ssl:
  388.         proxy = os.environ.get('https_proxy')
  389.         if proxy:
  390.             (p_server, p_port, p_ssl, p_uri) = ProcessUrl(service, proxy, True)
  391.             proxy_username = os.environ.get('proxy-username')
  392.             if not proxy_username:
  393.                 proxy_username = os.environ.get('proxy_username')
  394.             
  395.             proxy_password = os.environ.get('proxy-password')
  396.             if not proxy_password:
  397.                 proxy_password = os.environ.get('proxy_password')
  398.             
  399.             if proxy_username:
  400.                 user_auth = base64.encodestring('%s:%s' % (proxy_username, proxy_password))
  401.                 proxy_authorization = 'Proxy-authorization: Basic %s\r\n' % user_auth.strip()
  402.             else:
  403.                 proxy_authorization = ''
  404.             proxy_connect = 'CONNECT %s:%s HTTP/1.0\r\n' % (server, port)
  405.             user_agent = 'User-Agent: %s\r\n' % service.additional_headers['User-Agent']
  406.             proxy_pieces = proxy_connect + proxy_authorization + user_agent + '\r\n'
  407.             p_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  408.             p_sock.connect((p_server, p_port))
  409.             p_sock.sendall(proxy_pieces)
  410.             response = ''
  411.             while response.find('\r\n\r\n') == -1:
  412.                 response += p_sock.recv(8192)
  413.             p_status = response.split()[1]
  414.             if p_status != str(200):
  415.                 raise 'Error status=', str(p_status)
  416.             p_status != str(200)
  417.             ssl = socket.ssl(p_sock, None, None)
  418.             fake_sock = httplib.FakeSocket(p_sock, ssl)
  419.             connection = httplib.HTTPConnection(server)
  420.             connection.sock = fake_sock
  421.             full_uri = partial_uri
  422.         else:
  423.             connection = httplib.HTTPSConnection(server, port)
  424.             full_uri = partial_uri
  425.     else:
  426.         proxy = os.environ.get('http_proxy')
  427.         if proxy:
  428.             (p_server, p_port, p_ssl, p_uri) = ProcessUrl(service.server, proxy, True)
  429.             proxy_username = os.environ.get('proxy-username')
  430.             if not proxy_username:
  431.                 proxy_username = os.environ.get('proxy_username')
  432.             
  433.             proxy_password = os.environ.get('proxy-password')
  434.             if not proxy_password:
  435.                 proxy_password = os.environ.get('proxy_password')
  436.             
  437.             if proxy_username:
  438.                 UseBasicAuth(service, proxy_username, proxy_password, True)
  439.             
  440.             connection = httplib.HTTPConnection(p_server, p_port)
  441.             if not full_uri.startswith('http://'):
  442.                 if full_uri.startswith('/'):
  443.                     full_uri = 'http://%s%s' % (service.server, full_uri)
  444.                 else:
  445.                     full_uri = 'http://%s/%s' % (service.server, full_uri)
  446.             
  447.         else:
  448.             connection = httplib.HTTPConnection(server, port)
  449.             full_uri = partial_uri
  450.     return (connection, full_uri)
  451.  
  452.  
  453. def UseBasicAuth(service, username, password, for_proxy = False):
  454.     '''Sets an Authenticaiton: Basic HTTP header containing plaintext.
  455.  
  456.   Deprecated, use AtomService.use_basic_auth insread.
  457.   
  458.   The username and password are base64 encoded and added to an HTTP header
  459.   which will be included in each request. Note that your username and 
  460.   password are sent in plaintext. The auth header is added to the 
  461.   additional_headers dictionary in the service object.
  462.  
  463.   Args:
  464.     service: atom.AtomService or a subclass which has an 
  465.         additional_headers dict as a member.
  466.     username: str
  467.     password: str
  468.   '''
  469.     deprecation('calling deprecated function UseBasicAuth')
  470.     base_64_string = base64.encodestring('%s:%s' % (username, password))
  471.     base_64_string = base_64_string.strip()
  472.     if for_proxy:
  473.         header_name = 'Proxy-Authorization'
  474.     else:
  475.         header_name = 'Authorization'
  476.     service.additional_headers[header_name] = 'Basic %s' % (base_64_string,)
  477.  
  478.  
  479. def ProcessUrl(service, url, for_proxy = False):
  480.     '''Processes a passed URL.  If the URL does not begin with https?, then
  481.   the default value for server is used
  482.  
  483.   This method is deprecated, use atom.url.parse_url instead.
  484.   '''
  485.     if not isinstance(url, atom.url.Url):
  486.         url = atom.url.parse_url(url)
  487.     
  488.     server = url.host
  489.     ssl = False
  490.     port = 80
  491.     if not server:
  492.         if hasattr(service, 'server'):
  493.             server = service.server
  494.         else:
  495.             server = service
  496.         if not (url.protocol) and hasattr(service, 'ssl'):
  497.             ssl = service.ssl
  498.         
  499.         if hasattr(service, 'port'):
  500.             port = service.port
  501.         
  502.     elif url.protocol == 'https':
  503.         ssl = True
  504.     elif url.protocol == 'http':
  505.         ssl = False
  506.     
  507.     if url.port:
  508.         port = int(url.port)
  509.     elif port == 80 and ssl:
  510.         port = 443
  511.     
  512.     return (server, port, ssl, url.get_request_uri())
  513.  
  514.  
  515. def DictionaryToParamList(url_parameters, escape_params = True):
  516.     """Convert a dictionary of URL arguments into a URL parameter string.
  517.  
  518.   This function is deprcated, use atom.url.Url instead.
  519.  
  520.   Args:
  521.     url_parameters: The dictionaty of key-value pairs which will be converted
  522.                     into URL parameters. For example,
  523.                     {'dry-run': 'true', 'foo': 'bar'}
  524.                     will become ['dry-run=true', 'foo=bar'].
  525.  
  526.   Returns:
  527.     A list which contains a string for each key-value pair. The strings are
  528.     ready to be incorporated into a URL by using '&'.join([] + parameter_list)
  529.   """
  530.     transform_op = [
  531.         str,
  532.         urllib.quote_plus][bool(escape_params)]
  533.     if not url_parameters:
  534.         pass
  535.     parameter_tuples = [ (transform_op(param), transform_op(value)) for param, value in { }.items() ]
  536.     return [ '='.join(x) for x in parameter_tuples ]
  537.  
  538.  
  539. def BuildUri(uri, url_params = None, escape_params = True):
  540.     """Converts a uri string and a collection of parameters into a URI.
  541.  
  542.   This function is deprcated, use atom.url.Url instead.
  543.  
  544.   Args:
  545.     uri: string
  546.     url_params: dict (optional)
  547.     escape_params: boolean (optional)
  548.     uri: string The start of the desired URI. This string can alrady contain
  549.          URL parameters. Examples: '/base/feeds/snippets', 
  550.          '/base/feeds/snippets?bq=digital+camera'
  551.     url_parameters: dict (optional) Additional URL parameters to be included
  552.                     in the query. These are translated into query arguments
  553.                     in the form '&dict_key=value&...'.
  554.                     Example: {'max-results': '250'} becomes &max-results=250
  555.     escape_params: boolean (optional) If false, the calling code has already
  556.                    ensured that the query will form a valid URL (all
  557.                    reserved characters have been escaped). If true, this
  558.                    method will escape the query and any URL parameters
  559.                    provided.
  560.  
  561.   Returns:
  562.     string The URI consisting of the escaped URL parameters appended to the
  563.     initial uri string.
  564.   """
  565.     parameter_list = DictionaryToParamList(url_params, escape_params)
  566.     if parameter_list:
  567.         if uri.find('?') != -1:
  568.             full_uri = '&'.join([
  569.                 uri] + parameter_list)
  570.         else:
  571.             full_uri = '%s%s' % (uri, '?%s' % '&'.join([] + parameter_list))
  572.     else:
  573.         full_uri = uri
  574.     return full_uri
  575.  
  576.  
  577. def HttpRequest(service, operation, data, uri, extra_headers = None, url_params = None, escape_params = True, content_type = 'application/atom+xml'):
  578.     """Performs an HTTP call to the server, supports GET, POST, PUT, and DELETE.
  579.   
  580.   This method is deprecated, use atom.http.HttpClient.request instead.
  581.  
  582.   Usage example, perform and HTTP GET on http://www.google.com/:
  583.     import atom.service
  584.     client = atom.service.AtomService()
  585.     http_response = client.Get('http://www.google.com/')
  586.   or you could set the client.server to 'www.google.com' and use the 
  587.   following:
  588.     client.server = 'www.google.com'
  589.     http_response = client.Get('/')
  590.  
  591.   Args:
  592.     service: atom.AtomService object which contains some of the parameters 
  593.         needed to make the request. The following members are used to 
  594.         construct the HTTP call: server (str), additional_headers (dict), 
  595.         port (int), and ssl (bool).
  596.     operation: str The HTTP operation to be performed. This is usually one of
  597.         'GET', 'POST', 'PUT', or 'DELETE'
  598.     data: ElementTree, filestream, list of parts, or other object which can be 
  599.         converted to a string. 
  600.         Should be set to None when performing a GET or PUT.
  601.         If data is a file-like object which can be read, this method will read
  602.         a chunk of 100K bytes at a time and send them. 
  603.         If the data is a list of parts to be sent, each part will be evaluated
  604.         and sent.
  605.     uri: The beginning of the URL to which the request should be sent. 
  606.         Examples: '/', '/base/feeds/snippets', 
  607.         '/m8/feeds/contacts/default/base'
  608.     extra_headers: dict of strings. HTTP headers which should be sent
  609.         in the request. These headers are in addition to those stored in 
  610.         service.additional_headers.
  611.     url_params: dict of strings. Key value pairs to be added to the URL as
  612.         URL parameters. For example {'foo':'bar', 'test':'param'} will 
  613.         become ?foo=bar&test=param.
  614.     escape_params: bool default True. If true, the keys and values in 
  615.         url_params will be URL escaped when the form is constructed 
  616.         (Special characters converted to %XX form.)
  617.     content_type: str The MIME type for the data being sent. Defaults to
  618.         'application/atom+xml', this is only used if data is set.
  619.   """
  620.     deprecation('call to deprecated function HttpRequest')
  621.     full_uri = BuildUri(uri, url_params, escape_params)
  622.     (connection, full_uri) = PrepareConnection(service, full_uri)
  623.     if extra_headers is None:
  624.         extra_headers = { }
  625.     
  626.     if service.debug:
  627.         connection.debuglevel = 1
  628.     
  629.     connection.putrequest(operation, full_uri)
  630.     if data and not service.additional_headers.has_key('Content-Length') and not extra_headers.has_key('Content-Length'):
  631.         content_length = CalculateDataLength(data)
  632.         if content_length:
  633.             extra_headers['Content-Length'] = str(content_length)
  634.         
  635.     
  636.     if content_type:
  637.         extra_headers['Content-Type'] = content_type
  638.     
  639.     if isinstance(service.additional_headers, dict):
  640.         for header in service.additional_headers:
  641.             connection.putheader(header, service.additional_headers[header])
  642.         
  643.     
  644.     if isinstance(extra_headers, dict):
  645.         for header in extra_headers:
  646.             connection.putheader(header, extra_headers[header])
  647.         
  648.     
  649.     connection.endheaders()
  650.     if data:
  651.         if isinstance(data, list):
  652.             for data_part in data:
  653.                 __SendDataPart(data_part, connection)
  654.             
  655.         else:
  656.             __SendDataPart(data, connection)
  657.     
  658.     return connection.getresponse()
  659.  
  660.  
  661. def __SendDataPart(data, connection):
  662.     '''This method is deprecated, use atom.http._send_data_part'''
  663.     deprecated('call to deprecated function __SendDataPart')
  664.     if isinstance(data, str):
  665.         connection.send(data)
  666.         return None
  667.     if ElementTree.iselement(data):
  668.         connection.send(ElementTree.tostring(data))
  669.         return None
  670.     if hasattr(data, 'read'):
  671.         while None:
  672.             binarydata = data.read(100000)
  673.             continue
  674.             return None
  675.             None if binarydata == '' else isinstance(data, str)
  676.             connection.send(str(data))
  677.             return None
  678.             return None
  679.  
  680.  
  681. def CalculateDataLength(data):
  682.     '''Attempts to determine the length of the data to send. 
  683.   
  684.   This method will respond with a length only if the data is a string or
  685.   and ElementTree element.
  686.  
  687.   Args:
  688.     data: object If this is not a string or ElementTree element this funtion
  689.         will return None.
  690.   '''
  691.     if isinstance(data, str):
  692.         return len(data)
  693.     if isinstance(data, list):
  694.         return None
  695.     if ElementTree.iselement(data):
  696.         return len(ElementTree.tostring(data))
  697.     if hasattr(data, 'read'):
  698.         return None
  699.     return len(str(data))
  700.  
  701.  
  702. def deprecation(message):
  703.     warnings.warn(message, DeprecationWarning, stacklevel = 2)
  704.  
  705.