# A middleware that adds cookie support.

from Cookie import SimpleCookie as Cookie
from pump.util import codec

# Adds a "cookies" key to the request, which contains a dictionary containing
# any cookies sent by the client.  If any new values are found in the
# dictionary after your app is called, the new cookies are sent to the client.
# The values in the dict will be converted to strings, unless they are
# themselves dicts.  In that case, the "value" key will be used as the cookie
# value and the other keys will be interpreted as cookie attributes.
# 
#     request["cookies"] = {"a": {"value": "b", "path": "/"}}
# 
# Note: if a cookie is set and is later deleted from request["cookies"], the
# corresponding cookie will not automatically be deleted.  You need to set the
# "expires" attribute of the cookie to a time in the past.
def wrap_cookies(app):
  def wrapped_app(request):
    # Get any cookies from the request.
    req_cookies = request.get("cookies")
    if not req_cookies:
      req_cookies = _parse_cookies(request)
    request["cookies"] = req_cookies

    response = app(request)

    # If the app modified request["cookies"], set the new cookies.
    updated_cookies = request.get("cookies", {}).copy()
    cookie_header = []
    for k, v in updated_cookies.iteritems():
      v = str(v)
      if k not in req_cookies or req_cookies[k] != v:
        cookie_header.append(_format_cookie(k, v))

    response.setdefault("headers", {})["set_cookie"] = cookie_header
    return response
  return wrapped_app

# Parse the cookies from a request into a dictionary.
def _parse_cookies(request):
  cookie = Cookie(request["headers"].get("cookie"))
  parsed = {}
  for k, v in cookie.iteritems():
    parsed[k] = v.value
  return parsed

# Formats the dict of cookies for the set_cookie header.  If a value is a dict,
# its "value" key will be used as the value and the other keys will be
# interpreted as cookie attributes.
def _format_cookie(key, val):
  if not isinstance(val, dict):
    val = {"value": val}

  cookie = Cookie()
  cookie[key] = val["value"]
  del val["value"]

  morsel = cookie[key]
  for k, v in val.iteritems():
    morsel[k] = v
  return morsel.OutputString()
# A middleware that adds cookie support.

from Cookie import SimpleCookie as Cookie
from pump.util import codec

# Adds a "cookies" key to the request, which contains a dictionary containing
# any cookies sent by the client.  If any new values are found in the
# dictionary after your app is called, the new cookies are sent to the client.
# The values in the dict will be converted to strings, unless they are
# themselves dicts.  In that case, the "value" key will be used as the cookie
# value and the other keys will be interpreted as cookie attributes.
# 
#     request["cookies"] = {"a": {"value": "b", "path": "/"}}
# 
# Note: if a cookie is set and is later deleted from request["cookies"], the
# corresponding cookie will not automatically be deleted.  You need to set the
# "expires" attribute of the cookie to a time in the past.
def wrap_cookies(app):
  def wrapped_app(request):
    # Get any cookies from the request.
    req_cookies = request.get("cookies")
    if not req_cookies:
      req_cookies = _parse_cookies(request)
    request["cookies"] = req_cookies

    response = app(request)

    # If the app modified request["cookies"], set the new cookies.
    updated_cookies = request.get("cookies", {}).copy()
    cookie_header = []
    for k, v in updated_cookies.iteritems():
      try:
        value = v.get("value")
      except AttributeError:
        value = str(v)
      if k not in req_cookies or req_cookies[k] != value:
        cookie_header.append(_format_cookie(k, v))

    response.setdefault("headers", {})["set_cookie"] = cookie_header
    return response
  return wrapped_app

# Parse the cookies from a request into a dictionary.
def _parse_cookies(request):
  cookie = Cookie(request["headers"].get("cookie"))
  parsed = {}
  for k, v in cookie.iteritems():
    parsed[k] = v.value
  return parsed

# Formats the dict of cookies for the set_cookie header.  If a value is a dict,
# its "value" key will be used as the value and the other keys will be
# interpreted as cookie attributes.
def _format_cookie(key, val):
  if not isinstance(val, dict):
    val = {"value": val}

  cookie = Cookie()
  cookie[key] = val["value"]
  del val["value"]

  morsel = cookie[key]
  for k, v in val.iteritems():
    morsel[k] = v
  return morsel.OutputString()

allow setting cookies with dict