docs: def get_normalized_parameters(request):
          """
          Returns a string that contains the parameters that must be signed.
          This function is called by SignatureMethod subclass CustomSignatureMethod_HMAC_SHA1
          """
          # See issues #10 and #12
          if ('Content-Type' not in request.headers or \
              request.headers.get('Content-Type').startswith('application/x-www-form-urlencoded')) \
              and not isinstance(request.data, basestring):
              data_and_params = dict(request.data.items() + request.params.items())
  
              for key,value in data_and_params.items():
                  request.data_and_params[to_utf8(key)] = to_utf8(value)
  
          if request.data_and_params.has_key('oauth_signature'):
              del request.data_and_params['oauth_signature']
  
          items = []
          for key, value in request.data_and_params.iteritems():
              # 1.0a/9.1.1 states that kvp must be sorted by key, then by value,
              # so we unpack sequence values into multiple items for sorting.
              if isinstance(value, basestring):
                  items.append((key, value))
              else:
                  try:
                      value = list(value)
                  except TypeError, e:
                      assert 'is not iterable' in str(e)
                      items.append((key, value))
                  else:
                      items.extend((key, item) for item in value)
  
          # Include any query string parameters included in the url
          query_string = urlparse(request.url)[4]
          items.extend([(to_utf8(k), to_utf8(v)) for k, v in OAuthHook._split_url_string(query_string).items()])
          items.sort()
  
          return urllib.urlencode(items).replace('+', '%20').replace('%7E', '~')