async def handle(self, params: MultiDict) -> HTTPResponse: http_request = self.request # Rebuild parameters without value, as in RFC 6794 sec. 3.1 new_params = MultiDict() for k, v in params.items(): if v: new_params.add(k, v) params = new_params logger.debug('Request params: %s', params) # Create context context = Context(http_request=http_request, http_params=params) try: # Authenticate end user context.owner = await authenticate_end_user(http_request, params) # Authenticate client context.client = await authenticate_client(http_request, params) # Get request class request_class = self.get_request_class(params) # Create OAuth2 request kwargs = {} request_fields = {f.name for f in fields(request_class)} for k, v in params.items(): if k in request_fields: kwargs[k] = v context.oauth2_request = request_class(**kwargs) # Prepare response oauth2_response = await self.create_stream(context) except HTTPException as exc: return exc except HTTPRequestError as exc: raise HTTPBadRequest(reason=str(exc.args[0])) except OAuth2Error as exc: oauth2_response = exc except Exception as exc: # pylint: disable=broad-except logger.error('%s: %s', type(exc), exc, exc_info=exc) oauth2_response = ServerError('Unexpected server error, ' 'please try later.') return self.create_response(context, oauth2_response)
def parse(self, post_data: MultiDict): self.clear() if isinstance(post_data, dict): post_data = MultiDict(post_data) self.incr_fields = set() for k, v in post_data.items(): # 提交多个相同值,等价于提交一个数组(用于formdata和urlencode形式) v_all = post_data.getall(k) if len(v_all) > 1: v = v_all if k.startswith('$'): continue elif k == 'returning': self.returning = True continue elif '.' in k: # TODO: 不允许 incr 和普通赋值同时出现 k, op = k.rsplit('.', 1) if op == 'incr': self.incr_fields.add(k) self[k] = v
def custom_conditions_query_dict(query: MultiDict, allowed_keys: List[str] = []): conditions = [] values = [] for key, val in query.items(): if key.startswith("_"): continue deconstruct = key.split(":", 1) if len(deconstruct) > 1: field = deconstruct[0] operator = deconstruct[1] else: field = key operator = "eq" if allowed_keys is not None and field not in allowed_keys: continue if operator not in operators_to_sql: continue vals = val.split(",") conditions.append("({})".format(" OR ".join( map( lambda v: operators_to_sql["is" if v == "null" else operator]. format(field), vals)))) values += map( lambda v: None if v == "null" else operators_to_sql_values[operator].format(v), vals) return conditions, values
def binance(args: tuple[str, URL], kwargs: dict[str, Any]) -> tuple[str, URL]: method: str = args[0] url: URL = args[1] data: dict[str, Any] = kwargs["data"] or {} headers: CIMultiDict = kwargs["headers"] session: aiohttp.ClientSession = kwargs["session"] key: str = session.__dict__["_apis"][Hosts.items[url.host].name][0] secret: bytes = session.__dict__["_apis"][Hosts.items[url.host].name][1] expires = str(int(time.time() * 1000)) if method == METH_GET: if url.scheme == "https": query = MultiDict(url.query) query.extend({"timestamp": expires}) query_string = "&".join(f"{k}={v}" for k, v in query.items()) signature = hmac.new( secret, query_string.encode(), hashlib.sha256 ).hexdigest() query.extend({"signature": signature}) url = url.with_query(query) args = ( method, url, ) else: data.update({"timestamp": expires}) body = FormData(data)() signature = hmac.new(secret, body._value, hashlib.sha256).hexdigest() body._value += f"&signature={signature}".encode() body._size = len(body._value) kwargs.update({"data": body}) headers.update({"X-MBX-APIKEY": key}) return args
def _query_to_dict(self, query: MultiDict): """ Return a dict with list as value from the MultiDict. The value will be wrapped in a list if the args spec is define as a list or if the multiple values are sent (i.e ?foo=1&foo=2) """ return { key: values if len(values := query.getall(key)) > 1 or key in self._is_multiple else value for key, value in query.items() }
def multidict_to_dict(x: MultiDict) -> dict: """ Funzione che converte un MultiDict in un dict :param x: MultiDict da convertire :type: MultiDict :return: dict corrispondente al MultiDict :rtype: dict """ return { k: v if hasattr(v, "__len__") and len(v) <= 1 else x.getall(k) for k, v in x.items() }
def implicit_tvals(self): tvals = dict() ret = defaultdict(NoClobberDict) tls = self.tlayers rls = self.rlayers tl_n = [t.category for t in tls] def _parse_spec(s): c, v = s.split('=') return (c, v.split(',')) for c in self.controls: tvs = [] for specs, region in c.tval_specs: wsd = MultiDict() for w in region: # wsd[self.values(w, rls)] = w rv = tuple(zip([l.category for l in rls], self.values(w, rls))) wsd[rv] = w for rl, ws in wsd.items(): tl_v = map(list, map(set, zip(*[self.values(w, tls) for w in sorted(ws)]))) assert len(tl_n) == len(tl_v) available = zip(tl_n, tl_v) tmp = dict(available + map(_parse_spec, specs.split('*'))) chunk = [(tl, rl) for tl in list(product(*[tmp[t] for t in tl_n]))] tvs.append(chunk) from itertools import combinations assert 0 == sum(map(len, [set.intersection(set(x), set(y)) for x, y in list(combinations(tvs, 2))])) for tv, rv in sorted(set(sum(tvs, []))): ret[tv][rv] = c return dict([(k, dict(v)) for k, v in ret.items()])
def _sort_matchups(self, section): def filter_key(matchup_entry): primary_team, opponent = matchup_entry if section == "Strongest Loss": return opponent in self._losers.getall(primary_team, []) elif section == "No Wins for the Effort": return primary_team not in self._winners elif section == "Dirty Cheater": return primary_team not in self._losers else: return opponent in self._winners.getall(primary_team, []) def groupby_key(matchup_entry): primary_team, opponent = matchup_entry primary_points = self._team_points(primary_team) opponent_points = self._team_points(opponent) if section in [ "Blowout of the Week", "Closest Matchup of the Week" ]: return primary_points - opponent_points else: return primary_points def sort_key(matchup_entry): primary_team, opponent = matchup_entry return ( groupby_key(matchup_entry), self._team_points(primary_team), self._team_points(opponent), ) if section == "Strongest Loss": entries = self._losers elif section == "No Wins for the Effort": entries = MultiDict(self._losers, **self._ties) elif section in ["Closest Matchup", "Dirty Cheater"]: entries = MultiDict(self._winners, **self._ties) else: entries = self._winners sorted_matchups = sorted(filter(filter_key, entries.items()), key=sort_key, reverse=self._reverse_sort(section)) return [(points, list(group)) for points, group in groupby(sorted_matchups, key=groupby_key)]
def _dict_convert(self, data) -> Dict: if isinstance(data, dict): return data elif isinstance(data, MultiDict): data = MultiDict(data) tmp = {} for k, v in data.items(): # 提交多个相同值,等价于提交一个数组(用于formdata和urlencode形式) v_all = data.getall(k) if len(v_all) > 1: v = v_all tmp[k] = v return tmp else: return dict(data)
def bybit(args: Tuple[str, URL], kwargs: Dict[str, Any]) -> Tuple[str, URL]: method: str = args[0] url: URL = args[1] data: Dict[str, Any] = kwargs['data'] or {} session: aiohttp.ClientSession = kwargs['session'] key: str = session.__dict__['_apis'][Hosts.items[url.host].name][0] secret: bytes = session.__dict__['_apis'][Hosts.items[ url.host].name][1] expires = str(int((time.time() + 1.0) * 1000)) if method == METH_GET: query = MultiDict(url.query) if url.scheme == 'https': query.extend({'api_key': key, 'timestamp': expires}) query_string = '&'.join(f'{k}={v}' for k, v in sorted(query.items())) sign = hmac.new(secret, query_string.encode(), hashlib.sha256).hexdigest() query.extend({'sign': sign}) else: path = f'{method}/realtime{expires}' signature = hmac.new(secret, path.encode(), hashlib.sha256).hexdigest() query.extend({ 'api_key': key, 'expires': expires, 'signature': signature }) url = url.with_query(query) args = ( method, url, ) else: data.update({'api_key': key, 'timestamp': expires}) body = FormData(sorted(data.items()))() sign = hmac.new(secret, body._value, hashlib.sha256).hexdigest() body._value += f'&sign={sign}'.encode() body._size = len(body._value) kwargs.update({'data': body}) return args
def builtin_conditions_query_dict(query: MultiDict): conditions = [] values = [] for key, val in query.items(): if not key.startswith("_"): continue deconstruct = key.split(":", 1) if len(deconstruct) > 1: field = deconstruct[0] operator = deconstruct[1] else: field = key operator = None # Tags if field == "_tags": tags = val.split(",") if operator == "likeany" or operator == "likeall": # `?_tags:likeany` => LIKE ANY (OR) # `?_tags:likeall` => LIKE ALL (AND) # Raw SQL: SELECT * FROM runs_v3 WHERE tags||system_tags::text LIKE ANY(array['{%runtime:dev%','%user:m%']'); # Psycopg SQL: SELECT * FROM runs_v3 WHERE tags||system_tags::text LIKE ANY(array[%s,%s]); # Values for Psycopg: ['%runtime:dev%','%user:m%'] compare = "ANY" if operator == "likeany" else "ALL" conditions.append( "tags||system_tags::text LIKE {}(array[{}])".format( compare, ",".join(["%s"] * len(tags)))) values += map(lambda t: "%{}%".format(t), tags) else: # `?_tags:any` => ?| (OR) # `?_tags:all` => ?& (AND) (default) compare = "?|" if operator == "any" else "?&" conditions.append("tags||system_tags {} array[{}]".format( compare, ",".join(["%s"] * len(tags)))) values += tags return conditions, values
def bybit(args: tuple[str, URL], kwargs: dict[str, Any]) -> tuple[str, URL]: method: str = args[0] url: URL = args[1] data: dict[str, Any] = kwargs["data"] or {} session: aiohttp.ClientSession = kwargs["session"] key: str = session.__dict__["_apis"][Hosts.items[url.host].name][0] secret: bytes = session.__dict__["_apis"][Hosts.items[url.host].name][1] if url.scheme == "https": expires = str(int((time.time() - 5.0) * 1000)) recv_window = ( "recv_window" if not url.path.startswith("/spot") else "recvWindow" ) auth_params = {"api_key": key, "timestamp": expires, recv_window: 10000} if method in (METH_GET, METH_DELETE): query = MultiDict(url.query) query.extend(auth_params) query_string = "&".join(f"{k}={v}" for k, v in sorted(query.items())) sign = hmac.new( secret, query_string.encode(), hashlib.sha256 ).hexdigest() query.extend({"sign": sign}) url = url.with_query(query) args = (method, url) else: data.update(auth_params) body = FormData(sorted(data.items()))() sign = hmac.new(secret, body._value, hashlib.sha256).hexdigest() body._value += f"&sign={sign}".encode() body._size = len(body._value) kwargs.update({"data": body}) elif url.scheme == "wss": query = MultiDict(url.query) expires = str(int((time.time() + 5.0) * 1000)) path = f"{method}/realtime{expires}" signature = hmac.new(secret, path.encode(), hashlib.sha256).hexdigest() query.extend({"api_key": key, "expires": expires, "signature": signature}) url = url.with_query(query) args = (method, url) return args
def parse(self, post_data: MultiDict): self.clear() if isinstance(post_data, dict): post_data = MultiDict(post_data) for k, v in post_data.items(): v_all = post_data.getall(k) if len(v_all) > 1: v = v_all if k.startswith('$'): continue elif k == '_inner_data': continue elif k == 'returning': self.returning = True continue elif '.' in k: k, op = k.rsplit('.', 1) v = UpdateInfo(k, op, v) self[k] = v
async def io(req: Request): if req.content_type == 'application/x-www-form-urlencoded': charset = req.charset or 'utf-8' out = MultiDict(req.query) bytes_body = await req.read() if bytes_body: out.extend( parse_qsl(bytes_body.rstrip().decode(charset), keep_blank_values=True, encoding=charset)) # Make immutable dict with auth[param] keys like auth_param res = MultiDictProxy( MultiDict(( k.startswith('auth[') and k.endswith(']') and 'auth_' + k[5:-1] or k, v, ) for k, v in out.items())) print('\n'.join('{}: {}'.format(k, v) for k, v in res.items())) return Response(status=200, text='OK')
def binance(args: Tuple[str, URL], kwargs: Dict[str, Any]) -> Tuple[str, URL]: method: str = args[0] url: URL = args[1] data: Dict[str, Any] = kwargs['data'] or {} headers: CIMultiDict = kwargs['headers'] session: aiohttp.ClientSession = kwargs['session'] key: str = session.__dict__['_apis'][Hosts.items[url.host].name][0] secret: bytes = session.__dict__['_apis'][Hosts.items[ url.host].name][1] expires = str(int(time.time() * 1000)) if method == METH_GET: if url.scheme == 'https': query = MultiDict(url.query) query.extend({'timestamp': expires}) query_string = '&'.join(f'{k}={v}' for k, v in query.items()) signature = hmac.new(secret, query_string.encode(), hashlib.sha256).hexdigest() query.extend({'signature': signature}) url = url.with_query(query) args = ( method, url, ) else: data.update({'timestamp': expires}) body = FormData(data)() signature = hmac.new(secret, body._value, hashlib.sha256).hexdigest() body._value += f'&signature={signature}'.encode() body._size = len(body._value) kwargs.update({'data': body}) headers.update({'X-MBX-APIKEY': key}) return args
def filter_from_conditions_query_dict(query: MultiDict, allowed_keys: List[str] = []): """ Gathers all custom conditions from request query and returns a filter function """ filters = [] def _no_op(item): return True for key, val in query.items(): if key.startswith("_") and not key.startswith('_tags'): continue # skip internal conditions except _tags deconstruct = key.split(":", 1) if len(deconstruct) > 1: field = deconstruct[0] operator = deconstruct[1] else: field = key operator = "eq" if allowed_keys is not None and field not in allowed_keys: continue # skip conditions on non-allowed fields if operator not in operators_to_filters and field != '_tags': continue # skip conditions with no known operators # Tags if field == "_tags": tags = val.split(",") _fils = [] # support likeany, likeall, any, all. default to all if operator == "likeany": joiner_fn = filter_or op = "re" elif operator == "likeall": joiner_fn = filter_and op = "re" elif operator == "any": joiner_fn = filter_or op = "co" else: joiner_fn = filter_and op = "co" def bound(op, term): _filter = operators_to_filters[op] return lambda item: _filter( item['tags'] + item['system_tags'], term ) if 'tags' in item and 'system_tags' in item else False for tag in tags: # Necessary to wrap value inside quotes as we are # checking for containment on a list that has been cast to a string _pattern = ".*{}.*".format(tag) if op == "re" else "'{}'" _val = _pattern.format(tag) _fils.append(bound(op, _val)) if len(_fils) == 0: _fil = _no_op elif len(_fils) == 1: _fil = _fils[0] else: _fil = reduce(joiner_fn, _fils) filters.append(_fil) # Default case else: vals = val.split(",") _val_filters = [] for val in vals: _val_filters.append(bound_filter(operator, val, field)) # OR with a no_op filter would break, so handle the case of no values separately. if len(_val_filters) == 0: _fil = _no_op elif len(_val_filters) == 1: _fil = _val_filters[0] else: # if multiple values, join filters with filter_or() _fil = reduce(filter_or, _val_filters) filters.append(_fil) _final_filter = reduce(filter_and, filters, _no_op) return _final_filter # return filters reduced with filter_and()
def __add__(self, subdict: multidict.MultiDict): return self.__class__(itertools.chain(self.items(), subdict.items()))