# Path: nudge/publisher.py
# class WSGIRequest(object):
# 
#     def __init__(self, req_dict):
#         # Should we use dictomatic here? (tiny slowdown)
#         # REVIEW: From the following items, it feels like we can remove the Dictomatic wrapper.
#         self.req = Dictomatic.wrap(req_dict)
#         self.start_time = time.time()
#         self.method = self.req.get('REQUEST_METHOD')
#         self.remote_ip = self.req.get('REMOTE_ADDR', self.req.get('HTTP_REMOTE_ADDR'))
#         self.body = self.req.get('wsgi.input').read()
#         self._buffer = ''
#         self.files = {}
# 
#     @lazyprop
#     def path(self):
#         return self.req['PATH_INFO']
# 
#     @lazyprop
#     def uri(self):
#         return '%s://%s%s' % (
#                 self.req['wsgi.url_scheme'],
#                 self.req['HTTP_HOST'],
#                 self.req['PATH_INFO']
#             )
# 
#     @lazyprop
#     def headers(self):
#         _headers = WSGIHeaders()
#         for k,v in self.req.iteritems():
#             if k.startswith('HTTP_'):
#                 _headers[k.replace('HTTP_', '').lower()] = v
#             elif k == 'CONTENT_TYPE':
#                 _headers['Content-Type'] = v
#         return _headers
# 
#     @lazyprop
#     def cookies(self):
#         ''' I am assuming it is valid to have multiple cookies with the same
#         name even though that seems silly.
# 
#         Also the individual cookies are split on the FIRST = so as to support
#         later = for unknown benefit.
# 
#         TODO - support/test with unicode?
#              - Maybe nuke the HTTP_COOKIE from regular headers?
#         '''
#         _cookies = {}
#         if 'HTTP_COOKIE' in self.req:
#             for cookie in self.req['HTTP_COOKIE'].split(';'):
#                 cookie = cookie.split('=')
#                 if len(cookie) < 2: # Empty values will still be >= 2
#                     continue
#                 if cookie[0] in _cookies:
#                     _cookies[cookie[0].strip()].append(
#                         '='.join(cookie[1:]).strip()
#                     )
#                 else:
#                     _cookies[cookie[0].strip()] = ['='.join(cookie[1:]).strip()]
#         return _cookies
# 
#     @lazyprop
#     def arguments(self):
#         _arguments = {}
#         _files = {}
#         try:
#             # First url decode
#             tmp = self.req.get('QUERY_STRING', '')
#             if tmp:
#                 # make sure to split before unquoting
#                 # to handle arg keys/values that contain & or =
#                 tmp = tmp.split('&')
#                 tmp = [a.split('=') for a in tmp]
#                 tmp = [map(urllib.unquote_plus, a) for a in tmp]
#                 # Consider making the unicode decoding type a Nudge option.
#                 tmp = [map(partial(unicode, encoding='utf-8'), a) for a in tmp]
#                 # Only keep args with k and v. f= will stay and be [u'f', u'']
#                 tmp = filter(lambda x: len(x) == 2, tmp)
#                 for k, v in tmp:
#                     if k in _arguments:
#                         _arguments[k].append(v)
#                     else:
#                         _arguments[k] = [v]
#         except (Exception), e:
#             _log.exception(
#                 "problem making arguments out of QUERY_STRING: %s",
#                 self.req['QUERY_STRING']
#             )
# 
#         if self.method in ('POST', 'PUT') and self.body:
#             content_type = self.headers.get("Content-Type", '')
#             # TODO make sure these come out as unicode
#             if content_type.startswith("application/x-www-form-urlencoded"):
#                 for name, values in cgi.parse_qs(self.body).iteritems():
#                     _arguments.setdefault(name, []).extend(values)
#             # multipart form
#             elif content_type.startswith("multipart/form-data"):
#                 try:
#                     fs = cgi.FieldStorage(
#                         fp=StringIO.StringIO(self.body),
#                         environ=self.req,
#                         keep_blank_values=1
#                     )
#                     for k in fs.keys():
#                         part = fs[k]
#                         if part.filename:
#                             _files[k] = part
#                         _arguments[k] = part.value
#                 except:
#                     _log.exception(
#                         "problem parsing multipart/form-data"
#                     )
#             # add any arguments from JSON body
#             elif content_type.startswith("application/json"):
#                 try:
#                     body = nudge.json.json_decode(self.body)
#                     if isinstance(body, types.DictType):
#                         _arguments = dict(_arguments, **body)
# 
#                 except (ValueError):
#                     raise HTTPException(400, "body is not JSON")
# 
#         self.files = _files
#         return _arguments
# 
#     def write(self, content):
#         self._buffer += content
# 
#     def request_time(self):
#         return time.time() - self.start_time


import copy
import datetime
import unittest
import StringIO
import nudge.arg as args
import nudge.json as json
import nudge.publisher as servicepublisher
import nudge.validator as vals
from nose.tools import raises
from nudge.publisher import WSGIRequest
    def test_dict_in_body(self):
        req = create_json_post_req({
            "body":'{"test":{"two":3}}',
            "REQUEST_METHOD":"POST",
        })
        i = args.Dict("test")
        self.assertEqual({"two":3}, i.argspec(req, None))

    @raises(servicepublisher.HTTPException)
    def test_dict_in_body_fail(self):
        req = create_json_post_req({
            "arguments":{},"body":'{"test":1}',
            "REQUEST_METHOD":"POST",
        })
        i = args.Dict("test")
        self.assertEqual([], i.argspec(req, None))

    def test_uploaded_file(self):
        input = StringIO.StringIO('''
-----------------------------41184676334
Content-Disposition: form-data; name="caption"

Summer vacation
-----------------------------41184676334
Content-Disposition: form-data; name="upload"; filename="extra_data.txt"
Content-Type: text/plain

Some more data about my vacation
-----------------------------41184676334--
''')

# Path: nudge/publisher.py
# class WSGIRequest(object):
# 
#     def __init__(self, req_dict):
#         # Should we use dictomatic here? (tiny slowdown)
#         # REVIEW: From the following items, it feels like we can remove the Dictomatic wrapper.
#         self.req = Dictomatic.wrap(req_dict)
#         self.start_time = time.time()
#         self.method = self.req.get('REQUEST_METHOD')
#         self.remote_ip = self.req.get('REMOTE_ADDR', self.req.get('HTTP_REMOTE_ADDR'))
#         self.body = self.req.get('wsgi.input').read()
#         self._buffer = ''
#         self.files = {}
# 
#     @lazyprop
#     def path(self):
#         return self.req['PATH_INFO']
# 
#     @lazyprop
#     def uri(self):
#         return '%s://%s%s' % (
#                 self.req['wsgi.url_scheme'],
#                 self.req['HTTP_HOST'],
#                 self.req['PATH_INFO']
#             )
# 
#     @lazyprop
#     def headers(self):
#         _headers = WSGIHeaders()
#         for k,v in self.req.iteritems():
#             if k.startswith('HTTP_'):
#                 _headers[k.replace('HTTP_', '').lower()] = v
#             elif k == 'CONTENT_TYPE':
#                 _headers['Content-Type'] = v
#         return _headers
# 
#     @lazyprop
#     def cookies(self):
#         ''' I am assuming it is valid to have multiple cookies with the same
#         name even though that seems silly.
# 
#         Also the individual cookies are split on the FIRST = so as to support
#         later = for unknown benefit.
# 
#         TODO - support/test with unicode?
#              - Maybe nuke the HTTP_COOKIE from regular headers?
#         '''
#         _cookies = {}
#         if 'HTTP_COOKIE' in self.req:
#             for cookie in self.req['HTTP_COOKIE'].split(';'):
#                 cookie = cookie.split('=')
#                 if len(cookie) < 2: # Empty values will still be >= 2
#                     continue
#                 if cookie[0] in _cookies:
#                     _cookies[cookie[0].strip()].append(
#                         '='.join(cookie[1:]).strip()
#                     )
#                 else:
#                     _cookies[cookie[0].strip()] = ['='.join(cookie[1:]).strip()]
#         return _cookies
# 
#     @lazyprop
#     def arguments(self):
#         _arguments = {}
#         _files = {}
#         try:
#             # First url decode
#             tmp = self.req.get('QUERY_STRING', '')
#             if tmp:
#                 # make sure to split before unquoting
#                 # to handle arg keys/values that contain & or =
#                 tmp = tmp.split('&')
#                 tmp = [a.split('=') for a in tmp]
#                 tmp = [map(urllib.unquote_plus, a) for a in tmp]
#                 # Consider making the unicode decoding type a Nudge option.
#                 tmp = [map(partial(unicode, encoding='utf-8'), a) for a in tmp]
#                 # Only keep args with k and v. f= will stay and be [u'f', u'']
#                 tmp = filter(lambda x: len(x) == 2, tmp)
#                 for k, v in tmp:
#                     if k in _arguments:
#                         _arguments[k].append(v)
#                     else:
#                         _arguments[k] = [v]
#         except (Exception), e:
#             _log.exception(
#                 "problem making arguments out of QUERY_STRING: %s",
#                 self.req['QUERY_STRING']
#             )
# 
#         if self.method in ('POST', 'PUT') and self.body:
#             content_type = self.headers.get("Content-Type", '')
#             # TODO make sure these come out as unicode
#             if content_type.startswith("application/x-www-form-urlencoded"):
#                 for name, values in cgi.parse_qs(self.body).iteritems():
#                     _arguments.setdefault(name, []).extend(values)
#             # multipart form
#             elif content_type.startswith("multipart/form-data"):
#                 try:
#                     fs = cgi.FieldStorage(
#                         fp=StringIO.StringIO(self.body),
#                         environ=self.req,
#                         keep_blank_values=1
#                     )
#                     for k in fs.keys():
#                         part = fs[k]
#                         if part.filename:
#                             _files[k] = part
#                         _arguments[k] = part.value
#                 except:
#                     _log.exception(
#                         "problem parsing multipart/form-data"
#                     )
#             # add any arguments from JSON body
#             elif content_type.startswith("application/json"):
#                 try:
#                     body = nudge.json.json_decode(self.body)
#                     if isinstance(body, types.DictType):
#                         _arguments = dict(_arguments, **body)
# 
#                 except (ValueError):
#                     raise HTTPException(400, "body is not JSON")
# 
#         self.files = _files
#         return _arguments
# 
#     def write(self, content):
#         self._buffer += content
# 
#     def request_time(self):
#         return time.time() - self.start_time


# Path: tests/test_args.py
import copy
import datetime
import unittest
import StringIO
import nudge.arg as args
import nudge.json as json
import nudge.publisher as servicepublisher
import nudge.validator as vals
from nose.tools import raises
from nudge.publisher import WSGIRequest

    def test_dict_in_body(self):
        req = create_json_post_req({
            "body":'{"test":{"two":3}}',
            "REQUEST_METHOD":"POST",
        })
        i = args.Dict("test")
        self.assertEqual({"two":3}, i.argspec(req, None))

    @raises(servicepublisher.HTTPException)
    def test_dict_in_body_fail(self):
        req = create_json_post_req({
            "arguments":{},"body":'{"test":1}',
            "REQUEST_METHOD":"POST",
        })
        i = args.Dict("test")
        self.assertEqual([], i.argspec(req, None))

    def test_uploaded_file(self):
        input = StringIO.StringIO('''
-----------------------------41184676334
Content-Disposition: form-data; name="caption"

Summer vacation
-----------------------------41184676334
Content-Disposition: form-data; name="upload"; filename="extra_data.txt"
Content-Type: text/plain

Some more data about my vacation
-----------------------------41184676334--
''')

        request = WSGIRequest({