Beispiel #1
0
    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)
Beispiel #2
0
    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
Beispiel #3
0
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
Beispiel #4
0
    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
Beispiel #5
0
    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()
        }
Beispiel #6
0
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()])
Beispiel #8
0
    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)]
Beispiel #9
0
    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)
Beispiel #10
0
    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
Beispiel #11
0
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
Beispiel #12
0
    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
Beispiel #13
0
    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
Beispiel #14
0
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')
Beispiel #15
0
    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
Beispiel #16
0
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()))