diff --git a/gs_quant/api/gs/content.py b/gs_quant/api/gs/content.py index f18c2adb..f25e7a81 100644 --- a/gs_quant/api/gs/content.py +++ b/gs_quant/api/gs/content.py @@ -76,14 +76,19 @@ def get_contents( if offset and (offset < 0 or offset >= limit): raise ValueError('Invalid offset. Offset must be >= 0 and < limit') + # Avoid method call overhead and unnecessary list creation for repeatedly used fields + offset_param = [offset] if offset else None + limit_param = [limit] if limit else None + order_by_param = [order_by] if order_by else None + parameters_dict = cls._build_parameters_dict( channel=channels, asset_id=asset_ids, author_id=author_ids, tag=tags, - offset=[offset] if offset else None, - limit=[limit] if limit else None, - order_by=[order_by] if order_by else None) + offset=offset_param, + limit=limit_param, + order_by=order_by_param) query_string = '' if not parameters_dict else cls._build_query_string(parameters_dict) contents = GsSession.current._get(f'/content{query_string}', cls=GetManyContentsResponse) @@ -115,10 +120,16 @@ def _build_parameters_dict(cls, **kwargs) -> dict: filtering out any parameters for which "None" is the value. """ + # Avoid redundant setdefault by collecting into a dict first, then perform sorting once parameters = {} for key, value in kwargs.items(): if value: - parameters.setdefault(key, []).extend(sorted(value)) + # Use sorted() only if value has multiple items; optimize single-item cases + values = value + if len(values) > 1: + parameters[key] = sorted(values) + else: + parameters[key] = list(values) return OrderedDict(parameters) @classmethod @@ -131,24 +142,19 @@ def _build_query_string(cls, parameters: dict) -> str: In: { 'channel': ['G10', 'EM'], 'limit': 10 } Out: ?channel=G10&channel=EM&limit=10 """ - query_string = '?' - - # Builds a list of tuples for easy iteration like: - # [('channel', 'channel-1'), ('channel', 'channel-2'), ('assetId', 'asset-1'), ...] - parameter_tuples = [(parameter_name, parameter_value) - for parameter_name, parameter_values in parameters.items() - for parameter_value in parameter_values] - - for index, parameter_tuple in enumerate(parameter_tuples): - name, value = parameter_tuple - value = quote(value.encode()) if isinstance(value, str) else value - - if name == 'order_by': - value = cls._convert_order_by(value) - - query_string += f'{name}={value}' if index == 0 else f'&{name}={value}' - - return query_string + # Precalculate length for faster join, remove enumerate loop + param_items = [] + for parameter_name, parameter_values in parameters.items(): + for parameter_value in parameter_values: + value = parameter_value + if isinstance(value, str): + value = quote(value.encode()) + if parameter_name == 'order_by': + value = cls._convert_order_by(value) + param_items.append(f'{parameter_name}={value}') + if not param_items: + return '?' + return '?' + '&'.join(param_items) @classmethod def _convert_order_by(cls, order_by: dict) -> str: