def __init__(self, mapping=None): self.__d = {} # First, handle initializing from other MultiDicts. if isinstance(mapping, MultiDict): for key, lst in mapping.iterlists(): self.setlist(key, lst) # Otherwise, if we're given another dictionary: elif isinstance(mapping, dict): for key, value in iteritems(mapping): # We convert lists of things to multidict lists. if isinstance(value, (list, tuple)): value = list(value) else: value = [value] self.setlist(key, value) # Otherwise, we assume this is some iterable of some sort. else: tmp = {} for key, value in (mapping or ()): tmp.setdefault(key, []).append(value) for key, lst in iteritems(tmp): self.setlist(key, lst)
def test_route(self, param): if 'skip' in param: if hasattr(unittest, 'SkipTest'): raise unittest.SkipTest(param['skip']) return matcher = Matcher(param['path']) regex = param['regex'].encode('latin-1') self.assertEqual(matcher.match_re.pattern, regex) class FakeRequest(object): path_info = None for succ in param.get('successes', []): r = FakeRequest() r.path_info = succ['route'].encode('latin-1') matched, args, kwargs = matcher.match(r) expected_args = [x.encode('latin-1') for x in succ.get('args', [])] expected_kwargs_str = succ.get('kwargs', {}) expected_kwargs = {} for k, v in iteritems(expected_kwargs_str): if isinstance(v, text_type): v = v.encode('latin-1') expected_kwargs[k] = v self.assertTrue(matched) self.assertEqual(args, expected_args) self.assertEqual(kwargs, expected_kwargs) for fail in param.get('failures', []): r = FakeRequest() r.path = fail matched, _, _ = matcher.match(r) self.assertFalse(matched)
def from_dict(self, d): """ Populates this dictionary with values from a given dictionary. All upper-case root keys in the given dictionary are added to this object. """ for key, val in iteritems(d): if key.isupper(): self[key] = val
def test_escape_table(self): from hoboken.objects.mixins.cookies import _escape_table for k, v in iteritems(_escape_table): if PY3: self.assertTrue(isinstance(k, int)) self.assertTrue(isinstance(v, bytes)) else: self.assertTrue(isinstance(k, bytes)) self.assertTrue(isinstance(v, bytes))
def extend(self, it): if isinstance(it, dict): for key, val in iteritems(it): if isinstance(val, (tuple, list)): for v in val: self.add(key, v) else: self.add(key, val) else: for key, val in it: self.add(key, val)
def test_cookie_serialization(self, param): if not param: return name = _e(param['values']['name']) value = _e(param['values']['value']) m = Morsel(name, value) for name, val in iteritems(param['values']['attributes']): setattr(m, name, _e(val)) output = _e(param['output']) self.assertEqual(m.serialize(), output)
def build(klass, path, **kwargs): """ This function lets us build a request by creating a base, empty WSGI environ, and then filling it in with the appropriate values. """ if PY3: # pragma: no cover # We encode bytes as strings. if isinstance(path, binary_type): path = path.decode('latin-1') else: # pragma: no cover # We encode unicode as a string. if isinstance(path, text_type): path = path.encode('latin-1') # Build a temporary environ. env = { 'SERVER_PROTOCOL': 'HTTP/1.0', 'SCRIPT_NAME': '', 'PATH_INFO': path, # WSGI variables. 'wsgi.version': (1, 0), 'wsgi.url_scheme': 'http', 'wsgi.multithread': False, 'wsgi.multiprocess': False, 'wsgi.run_once': False, } def try_add(arg, key, default=None): val = kwargs.get(arg, default) if val is not None: env[key] = val try_add('query_string', 'QUERY_STRING') try_add('method', 'REQUEST_METHOD', 'GET') try_add('server_name', 'SERVER_NAME', 'localhost') try_add('server_port', 'SERVER_PORT', '80') # Create our request. req = klass(env) # Set headers. headers = kwargs.get('headers') if headers is not None: for header, value in iteritems(headers): req.headers[header] = value # Done! return req
def serialize_auth(val): if isinstance(val, (tuple, list)): authtype, params = val if isinstance(params, dict): params = b', '.join( [k + b'="' + v + b'"' for k, v in iteritems(params)] ) if not isinstance(params, binary_type): msg = "Invalid type for 'params': %s" % (params.__class__.__name__) logger.warn(msg) raise ValueError(msg) return authtype + b' ' + params return val
def iter_multi_items(mapping): """ Iterate over the items in a mapping, properly handling more complex data structures. """ if isinstance(mapping, MultiDict): # Note: we don't unpack (key, value) from item. for item in mapping.iteritems(multi=True): yield item elif isinstance(mapping, MutableMapping): for key, value in iteritems(mapping): if isinstance(value, (tuple, list)): for value in value: yield key, value else: yield key, value else: for item in mapping: yield item
def _make_route(self, match, func): if isinstance(match, string_types): matcher = HobokenRouteMatcher(match) elif isinstance(match, RegexType): # match is a regex, so we extract any named groups. keys = [None] * match.groups types = [False] * match.groups for name, index in iteritems(match.groupindex): types[index - 1] = True keys[index - 1] = name # Append the route with these keys. matcher = RegexMatcher(match, types, keys) elif hasattr(match, "match") and callable(getattr(match, "match")): # Don't know what type it is, but it has a callable "match" # attribute, so we use that. matcher = match else: # Unknown type! raise InvalidMatchTypeException("Unknown type: %r" % (match, )) return Route(matcher, func)
def escape_string(self, string): base_escapes = { b'&': b'\\u0026', b'>': b'\\u003E', b'<': b'\\u003C' } escapes = base_escapes.copy() for k, v in iteritems(base_escapes): escapes[k.decode('latin-1')] = v.decode('latin-1') # Decode our unicode line/paragraph seperators. line_sep = b'\xE2\x80\xA8'.decode('utf-8') line_sep_escape = b'\\u2028'.decode('latin-1') paragraph_sep = b'\xE2\x80\xA9'.decode('utf-8') paragraph_sep_escape = b'\\u2029'.decode('latin-1') def encoder(match): v = match.group(0) return escapes[v] if isinstance(string, text_type): ret = re.sub(u(r"[&<>]"), encoder, string) return ret.replace(line_sep, line_sep_escape).replace( paragraph_sep, paragraph_sep_escape) else: return re.sub(br"[&<>]", encoder, string)
def _make_route(self, match, func): if isinstance(match, string_types): matcher = HobokenRouteMatcher(match) elif isinstance(match, RegexType): # match is a regex, so we extract any named groups. keys = [None] * match.groups types = [False] * match.groups for name, index in iteritems(match.groupindex): types[index - 1] = True keys[index - 1] = name # Append the route with these keys. matcher = RegexMatcher(match, types, keys) elif hasattr(match, "match") and callable(getattr(match, "match")): # Don't know what type it is, but it has a callable "match" # attribute, so we use that. matcher = match else: # Unknown type! raise InvalidMatchTypeException("Unknown type: %r" % (match,)) return Route(matcher, func)
def _handle_request(self): # Since these are thread-locals, we grab them as locals. request = self.request response = self.response self.logger.debug("Handling: %s %s", request.method, request.url) # Check for valid method. # TODO: Should this call our after filters? if request.method not in self.SUPPORTED_METHODS: self.logger.warn("Called with invalid method: %s", request.method) # TODO: hook. # Send "invalid method" exception. response.status_int = 405 return matched = False try: # Call before filters. for filter in self.before_filters: filter(request, response) # For each route of the specified type, try to match it. matched = self._run_routes(request.method) # We special-case the HEAD method to fallback to GET. if request.method == 'HEAD' and not matched: # Run our routes against the 'GET' method. matched = self._run_routes('GET') except HaltRoutingException as ex: # Set the various parameters. if ex.code is not None: response.status_int = ex.code if ex.body is not None: # We pass the body through to on_returned_body. self.on_returned_body(request, response, ex.body) if ex.headers is not None: # Set each header. for header, value in iteritems(ex.headers): # Set this header. response.headers[header] = value # Must set this, or we get clobbered by the 404 handler. matched = True except Exception as e: # Also, check if the exception has other information attached, # like a code/body. self.on_exception(e) # Must set this, or we get clobbered by the 404 handler. matched = True finally: # Call our after filters for route in self.after_filters: route(request, response) if not matched: self.on_route_missing()
def test_unquoter_table(self): from hoboken.objects.mixins.cookies import _unquoter_table for k, v in iteritems(_unquoter_table): self.assertTrue(isinstance(k, bytes)) self.assertTrue(isinstance(v, bytes))
def _iter_hashitems(self): return iteritems(self)
def set_cache_control(self, **kwargs): for key, val in iteritems(kwargs): setattr(self.response.cache_control, key, val)
def to_list(self): return list(iteritems(self))
# 1. All safe characters are allowed, so we replace them with themselves. _escape_table.update((x, x) for x in _safe_chars) # 2. The characters ':' and ' ' can be used without escaping, too. _escape_table[':'] = ':' _escape_table[' '] = ' ' # 3. The escapes for quotes and slashes are special. _escape_table['"'] = r'\"' _escape_table['\\'] = r'\\' # Finally, we might need to convert this table to operate on bytes, if we're # on Python 3. if PY3: # pragma: no cover new = {} for k, v in iteritems(_escape_table): new[ord(k)] = v.encode('ascii') _escape_table = new # This map is used to unquote things. It contains two types of entries: # 1. '101' --> 'A' (octal --> single character) # 2. 'A' --> 'A' (character -> same character) _unquoter_table = dict(('%03o' % i, chr(i)) for i in range(256)) _unquoter_table.update((v, v) for v in list(_unquoter_table.values())) # Convert to Python3 format if necessary if PY3: new = {} for k, v in iteritems(_unquoter_table): new[k.encode('latin-1')] = v.encode('latin-1')