Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 28 additions & 22 deletions gs_quant/api/gs/content.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand All @@ -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:
Expand Down