lusid-sdk 2.0.50b0__py3-none-any.whl → 2.0.470__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of lusid-sdk might be problematic. Click here for more details.
- lusid/__init__.py +1117 -14
- lusid/api/__init__.py +69 -0
- lusid/api/abor_api.py +513 -179
- lusid/api/abor_configuration_api.py +25 -24
- lusid/api/allocations_api.py +12 -20
- lusid/api/blocks_api.py +6 -6
- lusid/api/calendars_api.py +16 -24
- lusid/api/chart_of_accounts_api.py +1745 -441
- lusid/api/compliance_api.py +71 -62
- lusid/api/configuration_recipe_api.py +1198 -56
- lusid/api/corporate_action_sources_api.py +8 -8
- lusid/api/custom_entities_api.py +6 -6
- lusid/api/cut_label_definitions_api.py +9 -17
- lusid/api/data_types_api.py +16 -32
- lusid/api/executions_api.py +6 -6
- lusid/api/funds_api.py +1119 -0
- lusid/api/instrument_event_types_api.py +1287 -0
- lusid/api/instruments_api.py +12 -20
- lusid/api/legacy_compliance_api.py +12 -12
- lusid/api/legal_entities_api.py +12 -12
- lusid/api/order_graph_api.py +12 -12
- lusid/api/order_instructions_api.py +6 -6
- lusid/api/order_management_api.py +495 -14
- lusid/api/orders_api.py +16 -24
- lusid/api/packages_api.py +6 -6
- lusid/api/persons_api.py +16 -24
- lusid/api/placements_api.py +12 -12
- lusid/api/portfolio_groups_api.py +6 -6
- lusid/api/portfolios_api.py +23 -39
- lusid/api/property_definitions_api.py +205 -0
- lusid/api/queryable_keys_api.py +211 -0
- lusid/api/quotes_api.py +20 -36
- lusid/api/reconciliations_api.py +410 -1978
- lusid/api/schemas_api.py +7 -15
- lusid/api/scopes_api.py +151 -0
- lusid/api/scripted_translation_api.py +30 -28
- lusid/api/staging_rule_set_api.py +885 -0
- lusid/api/transaction_configuration_api.py +22 -22
- lusid/api/transaction_portfolios_api.py +282 -577
- lusid/api_client.py +5 -3
- lusid/configuration.py +1 -1
- lusid/extensions/__init__.py +10 -7
- lusid/extensions/api_client.py +3 -1
- lusid/extensions/api_client_factory.py +156 -45
- lusid/extensions/api_configuration.py +124 -15
- lusid/extensions/configuration_loaders.py +2 -4
- lusid/extensions/proxy_config.py +8 -5
- lusid/extensions/socket_keep_alive.py +14 -15
- lusid/extensions/tcp_keep_alive_connector.py +93 -46
- lusid/models/__init__.py +1028 -13
- lusid/models/abor.py +9 -2
- lusid/models/abor_configuration.py +8 -8
- lusid/models/abor_configuration_request.py +9 -9
- lusid/models/abor_request.py +1 -1
- lusid/models/account.py +6 -1
- lusid/models/accumulation_event.py +104 -0
- lusid/models/address_key_compliance_parameter.py +5 -12
- lusid/models/address_key_list_compliance_parameter.py +3 -3
- lusid/models/address_key_option_definition.py +3 -1
- lusid/models/amortisation_event.py +4 -6
- lusid/models/{underlying_leg.py → asset_leg.py} +15 -15
- lusid/models/basket.py +3 -3
- lusid/models/block_and_order_id_request.py +78 -0
- lusid/models/block_and_orders.py +83 -0
- lusid/models/block_and_orders_create_request.py +77 -0
- lusid/models/block_and_orders_request.py +134 -0
- lusid/models/blocked_order_request.py +130 -0
- lusid/models/bond.py +13 -6
- lusid/models/bond_coupon_event.py +97 -0
- lusid/models/bond_default_event.py +8 -18
- lusid/models/bond_principal_event.py +97 -0
- lusid/models/book_transactions_request.py +97 -0
- lusid/models/bool_compliance_parameter.py +3 -3
- lusid/models/bool_list_compliance_parameter.py +3 -3
- lusid/models/branch_step.py +101 -0
- lusid/models/cap_floor.py +3 -3
- lusid/models/cash_dividend_event.py +32 -10
- lusid/models/cash_election.py +91 -0
- lusid/models/cash_flow_event.py +5 -7
- lusid/models/cash_perpetual.py +3 -3
- lusid/models/cds_flow_conventions.py +1 -1
- lusid/models/cds_index.py +4 -4
- lusid/models/check_step.py +110 -0
- lusid/models/cleardown_module_details.py +95 -0
- lusid/models/cleardown_module_request.py +117 -0
- lusid/models/cleardown_module_response.py +139 -0
- lusid/models/cleardown_module_rule.py +94 -0
- lusid/models/{reconciliation_run_break.py → cleardown_module_rules_updated_response.py} +30 -36
- lusid/models/close_event.py +3 -3
- lusid/models/close_period_diary_entry_request.py +149 -0
- lusid/models/complete_portfolio.py +8 -1
- lusid/models/complex_bond.py +4 -4
- lusid/models/complex_market_data.py +6 -5
- lusid/models/compliance_parameter.py +8 -5
- lusid/models/compliance_parameter_type.py +3 -0
- lusid/models/compliance_rule_breakdown.py +16 -8
- lusid/models/compliance_rule_breakdown_request.py +12 -4
- lusid/models/compliance_rule_result_v2.py +85 -0
- lusid/models/compliance_step.py +99 -0
- lusid/models/compliance_step_type.py +42 -0
- lusid/models/compliance_summary_rule_result.py +12 -15
- lusid/models/compliance_summary_rule_result_request.py +12 -15
- lusid/models/compliance_template_variation.py +12 -2
- lusid/models/component_transaction.py +92 -0
- lusid/models/composite_dispersion.py +30 -5
- lusid/models/compounding.py +4 -4
- lusid/models/configuration_recipe.py +10 -19
- lusid/models/constant_volatility_surface.py +102 -0
- lusid/models/contract_for_difference.py +3 -3
- lusid/models/create_derived_property_definition_request.py +3 -3
- lusid/models/create_derived_transaction_portfolio_request.py +10 -3
- lusid/models/create_property_definition_request.py +12 -5
- lusid/models/create_staging_rule_set_request.py +91 -0
- lusid/models/create_trade_tickets_response.py +87 -0
- lusid/models/create_transaction_portfolio_request.py +16 -3
- lusid/models/credit_default_swap.py +4 -4
- lusid/models/credit_spread_curve_data.py +4 -4
- lusid/models/custom_entity_definition.py +8 -2
- lusid/models/custom_entity_type.py +8 -2
- lusid/models/cut_label_definition.py +7 -1
- lusid/models/data_type.py +7 -1
- lusid/models/data_type_summary.py +8 -2
- lusid/models/date_time_compliance_parameter.py +3 -3
- lusid/models/date_time_list_compliance_parameter.py +3 -3
- lusid/models/{upsert_reconciliation_run_request.py → day_month.py} +15 -15
- lusid/models/decimal_compliance_parameter.py +3 -3
- lusid/models/decimal_list_compliance_parameter.py +3 -3
- lusid/models/dialect.py +9 -3
- lusid/models/diary_entry.py +1 -1
- lusid/models/diary_entry_request.py +1 -1
- lusid/models/discount_factor_curve_data.py +3 -3
- lusid/models/dividend_option_event.py +129 -0
- lusid/models/dividend_reinvestment_event.py +124 -0
- lusid/models/election_specification.py +73 -0
- lusid/models/eligibility_calculation.py +71 -0
- lusid/models/empty_model_options.py +3 -3
- lusid/models/equity.py +8 -6
- lusid/models/equity_curve_by_prices_data.py +3 -3
- lusid/models/equity_model_options.py +3 -3
- lusid/models/equity_option.py +3 -3
- lusid/models/equity_swap.py +4 -4
- lusid/models/equity_vol_surface_data.py +3 -3
- lusid/models/exchange_traded_option.py +3 -3
- lusid/models/exercise_event.py +5 -7
- lusid/models/exotic_instrument.py +3 -3
- lusid/models/expiry_event.py +91 -0
- lusid/models/filter_predicate_compliance_parameter.py +91 -0
- lusid/models/filter_step.py +101 -0
- lusid/models/fixed_leg.py +3 -3
- lusid/models/fixed_schedule.py +4 -9
- lusid/models/flexible_loan.py +105 -0
- lusid/models/float_schedule.py +20 -12
- lusid/models/floating_leg.py +3 -3
- lusid/models/flow_convention_name.py +1 -1
- lusid/models/flow_conventions.py +1 -1
- lusid/models/forward_rate_agreement.py +3 -3
- lusid/models/from_recipe.py +81 -0
- lusid/models/fund.py +182 -0
- lusid/models/fund_properties.py +115 -0
- lusid/models/fund_request.py +165 -0
- lusid/models/fund_share_class.py +99 -0
- lusid/models/funding_leg.py +3 -3
- lusid/models/funding_leg_options.py +3 -3
- lusid/models/future.py +3 -3
- lusid/models/fx_conventions.py +73 -0
- lusid/models/fx_forward.py +8 -6
- lusid/models/fx_forward_curve_by_quote_reference.py +4 -4
- lusid/models/fx_forward_curve_data.py +3 -3
- lusid/models/fx_forward_model_options.py +3 -3
- lusid/models/fx_forward_pips_curve_data.py +3 -3
- lusid/models/fx_forward_settlement_event.py +136 -0
- lusid/models/fx_forward_tenor_curve_data.py +4 -4
- lusid/models/fx_forward_tenor_pips_curve_data.py +4 -4
- lusid/models/fx_linked_notional_schedule.py +108 -0
- lusid/models/fx_option.py +3 -3
- lusid/models/fx_rate_schedule.py +3 -3
- lusid/models/fx_swap.py +4 -4
- lusid/models/fx_vol_surface_data.py +3 -3
- lusid/models/{reconciliation_run.py → get_recipe_composer_response.py} +15 -15
- lusid/models/group_by_selector_compliance_parameter.py +91 -0
- lusid/models/group_by_step.py +101 -0
- lusid/models/group_filter_predicate_compliance_parameter.py +91 -0
- lusid/models/group_filter_step.py +110 -0
- lusid/models/group_of_market_data_key_rules.py +79 -0
- lusid/models/index_convention.py +1 -1
- lusid/models/index_model_options.py +3 -3
- lusid/models/inflation_index_conventions.py +2 -2
- lusid/models/inflation_leg.py +3 -3
- lusid/models/inflation_linked_bond.py +3 -3
- lusid/models/inflation_swap.py +4 -4
- lusid/models/informational_error_event.py +3 -3
- lusid/models/informational_event.py +4 -6
- lusid/models/instrument_event.py +13 -5
- lusid/models/instrument_event_configuration.py +74 -0
- lusid/models/instrument_event_holder.py +12 -3
- lusid/models/instrument_event_type.py +8 -0
- lusid/models/instrument_leg.py +3 -3
- lusid/models/instrument_list_compliance_parameter.py +3 -3
- lusid/models/instrument_payment_diary_leg.py +5 -3
- lusid/models/instrument_resolution_detail.py +105 -0
- lusid/models/instrument_type.py +2 -0
- lusid/models/interest_rate_swap.py +4 -4
- lusid/models/interest_rate_swaption.py +3 -3
- lusid/models/intermediate_compliance_step.py +110 -0
- lusid/models/ir_vol_cube_data.py +3 -3
- lusid/models/journal_entry_line.py +34 -3
- lusid/models/journal_entry_lines_query_parameters.py +1 -1
- lusid/models/label_value_set.py +1 -1
- lusid/models/leg_definition.py +16 -3
- lusid/models/lineage_member.py +87 -0
- lusid/models/lock_period_diary_entry_request.py +91 -0
- lusid/models/lusid_instrument.py +7 -5
- lusid/models/lusid_trade_ticket.py +8 -1
- lusid/models/market_context.py +17 -2
- lusid/models/market_data_type.py +1 -0
- lusid/models/maturity_event.py +91 -0
- lusid/models/model_options.py +5 -6
- lusid/models/model_options_type.py +0 -1
- lusid/models/model_selection.py +3 -3
- lusid/models/move_orders_to_different_blocks_request.py +77 -0
- lusid/models/moved_order_to_different_block_response.py +85 -0
- lusid/models/movement_type.py +2 -0
- lusid/models/multi_currency_amounts.py +71 -0
- lusid/models/opaque_market_data.py +3 -3
- lusid/models/opaque_model_options.py +3 -3
- lusid/models/open_event.py +3 -3
- lusid/models/optionality_schedule.py +3 -3
- lusid/models/order_graph_block.py +4 -2
- lusid/models/order_graph_block_order_detail.py +16 -2
- lusid/models/output_transaction.py +9 -2
- lusid/models/paged_resource_list_of_cleardown_module_response.py +113 -0
- lusid/models/{paged_resource_list_of_reconciliation_run_break.py → paged_resource_list_of_cleardown_module_rule.py} +11 -11
- lusid/models/{paged_resource_list_of_reconciliation_run.py → paged_resource_list_of_fund.py} +11 -11
- lusid/models/paged_resource_list_of_property_definition.py +113 -0
- lusid/models/paged_resource_list_of_staging_rule_set.py +113 -0
- lusid/models/paged_resource_list_of_transaction_template.py +113 -0
- lusid/models/paged_resource_list_of_transaction_template_specification.py +113 -0
- lusid/models/participation_request.py +3 -9
- lusid/models/performance_returns_metric.py +1 -1
- lusid/models/period_diary_entries_reopened_response.py +104 -0
- lusid/models/place_blocks_request.py +77 -0
- lusid/models/portfolio.py +15 -2
- lusid/models/portfolio_details.py +15 -2
- lusid/models/portfolio_group_id_compliance_parameter.py +3 -3
- lusid/models/portfolio_group_id_list_compliance_parameter.py +3 -3
- lusid/models/portfolio_holding.py +27 -2
- lusid/models/portfolio_id_compliance_parameter.py +3 -3
- lusid/models/portfolio_id_list_compliance_parameter.py +3 -3
- lusid/models/posting_module_rule.py +29 -4
- lusid/models/pricing_model.py +2 -1
- lusid/models/property_definition.py +17 -4
- lusid/models/property_definition_search_result.py +3 -3
- lusid/models/property_domain.py +3 -0
- lusid/models/property_key_compliance_parameter.py +3 -3
- lusid/models/property_key_list_compliance_parameter.py +3 -3
- lusid/models/queryable_key.py +124 -0
- lusid/models/raw_vendor_event.py +5 -7
- lusid/models/re_open_period_diary_entry_request.py +84 -0
- lusid/models/recipe_block.py +87 -0
- lusid/models/recipe_composer.py +100 -0
- lusid/models/{reconciliation_break_id.py → recipe_value.py} +22 -23
- lusid/models/recombine_step.py +101 -0
- lusid/models/reference_instrument.py +3 -3
- lusid/models/relative_date_offset.py +71 -0
- lusid/models/repo.py +3 -3
- lusid/models/reset_event.py +4 -6
- lusid/models/resource_list_of_block_and_orders.py +113 -0
- lusid/models/resource_list_of_get_recipe_composer_response.py +113 -0
- lusid/models/resource_list_of_moved_order_to_different_block_response.py +113 -0
- lusid/models/resource_list_of_queryable_key.py +113 -0
- lusid/models/schedule.py +6 -5
- lusid/models/schedule_type.py +1 -0
- lusid/models/script_map_reference.py +94 -0
- lusid/models/security_election.py +86 -0
- lusid/models/set_share_class_instruments_request.py +79 -0
- lusid/models/side_definition.py +1 -8
- lusid/models/sides_definition_request.py +1 -8
- lusid/models/simple_cash_flow_loan.py +3 -3
- lusid/models/simple_instrument.py +3 -3
- lusid/models/staging_rule.py +90 -0
- lusid/models/staging_rule_approval_criteria.py +81 -0
- lusid/models/staging_rule_match_criteria.py +95 -0
- lusid/models/staging_rule_set.py +103 -0
- lusid/models/step_schedule.py +3 -3
- lusid/models/stock_split_event.py +3 -3
- lusid/models/string_compliance_parameter.py +3 -3
- lusid/models/string_list_compliance_parameter.py +3 -3
- lusid/models/template_field.py +77 -0
- lusid/models/term_deposit.py +3 -3
- lusid/models/total_return_swap.py +16 -16
- lusid/models/transaction_configuration_movement_data.py +3 -3
- lusid/models/transaction_configuration_movement_data_request.py +3 -3
- lusid/models/transaction_currency_and_amount.py +81 -0
- lusid/models/transaction_field_map.py +97 -0
- lusid/models/transaction_price.py +3 -3
- lusid/models/transaction_price_and_type.py +81 -0
- lusid/models/transaction_price_type.py +1 -0
- lusid/models/transaction_property_map.py +80 -0
- lusid/models/transaction_template.py +100 -0
- lusid/models/transaction_template_request.py +79 -0
- lusid/models/transaction_template_specification.py +99 -0
- lusid/models/transaction_type_alias.py +0 -7
- lusid/models/transaction_type_calculation.py +1 -1
- lusid/models/transition_event.py +3 -3
- lusid/models/translation_context.py +75 -0
- lusid/models/translation_script.py +9 -3
- lusid/models/trial_balance.py +46 -11
- lusid/models/trial_balance_query_parameters.py +15 -6
- lusid/models/trigger_event.py +3 -3
- lusid/models/units_ratio.py +71 -0
- lusid/models/update_staging_rule_set_request.py +91 -0
- lusid/models/{compliance_run_summary.py → upsert_compliance_run_summary_result.py} +8 -8
- lusid/models/upsert_dialect_request.py +79 -0
- lusid/models/upsert_instrument_event_request.py +12 -3
- lusid/models/upsert_quote_request.py +1 -1
- lusid/models/upsert_recipe_composer_request.py +73 -0
- lusid/models/upsert_recipe_request.py +3 -9
- lusid/models/upsert_translation_script_request.py +75 -0
- lusid/models/valuation_schedule.py +10 -3
- lusid/models/weighted_instrument.py +13 -2
- lusid/models/weighted_instrument_in_line_lookup_identifiers.py +89 -0
- lusid/models/yield_curve_data.py +3 -3
- lusid/rest.py +1 -1
- {lusid_sdk-2.0.50b0.dist-info → lusid_sdk-2.0.470.dist-info}/METADATA +245 -48
- {lusid_sdk-2.0.50b0.dist-info → lusid_sdk-2.0.470.dist-info}/RECORD +326 -235
- {lusid_sdk-2.0.50b0.dist-info → lusid_sdk-2.0.470.dist-info}/WHEEL +1 -1
- lusid/extensions/api_client_builder.py +0 -138
- lusid/models/configuration_recipe_snippet.py +0 -139
- lusid/models/je_lines_query_parameters.py +0 -105
- lusid/models/look_up_pricing_model_options.py +0 -93
- lusid/models/reconciliation_run_id.py +0 -85
- lusid/models/upsert_reconciliation_break_request.py +0 -98
lusid/api_client.py
CHANGED
|
@@ -214,6 +214,8 @@ class ApiClient:
|
|
|
214
214
|
url += "?" + url_query
|
|
215
215
|
|
|
216
216
|
try:
|
|
217
|
+
# if returning http_data_only then we need to deserialise response.
|
|
218
|
+
_preload_content = True if _return_http_data_only else _preload_content
|
|
217
219
|
# perform request and return response
|
|
218
220
|
response_data = await self.request(
|
|
219
221
|
method, url,
|
|
@@ -260,8 +262,8 @@ class ApiClient:
|
|
|
260
262
|
else:
|
|
261
263
|
return ApiResponse(status_code = response_data.status,
|
|
262
264
|
data = return_data,
|
|
263
|
-
headers = response_data.getheaders(),
|
|
264
|
-
raw_data = response_data.data)
|
|
265
|
+
headers = response_data.getheaders() if _preload_content else response_data.headers,
|
|
266
|
+
raw_data = response_data.data if _preload_content else response_data)
|
|
265
267
|
|
|
266
268
|
def sanitize_for_serialization(self, obj):
|
|
267
269
|
"""Builds a JSON POST object.
|
|
@@ -544,7 +546,7 @@ class ApiClient:
|
|
|
544
546
|
if k in collection_formats:
|
|
545
547
|
collection_format = collection_formats[k]
|
|
546
548
|
if collection_format == 'multi':
|
|
547
|
-
new_params.extend((k, value) for value in v)
|
|
549
|
+
new_params.extend((k, quote(str(value))) for value in v)
|
|
548
550
|
else:
|
|
549
551
|
if collection_format == 'ssv':
|
|
550
552
|
delimiter = ' '
|
lusid/configuration.py
CHANGED
|
@@ -373,7 +373,7 @@ class Configuration:
|
|
|
373
373
|
return "Python SDK Debug Report:\n"\
|
|
374
374
|
"OS: {env}\n"\
|
|
375
375
|
"Python Version: {pyversion}\n"\
|
|
376
|
-
"Version of the API: 0.11.
|
|
376
|
+
"Version of the API: 0.11.6417\n"\
|
|
377
377
|
"SDK Package Version: {package_version}".\
|
|
378
378
|
format(env=sys.platform, pyversion=sys.version, package_version=package_version)
|
|
379
379
|
|
lusid/extensions/__init__.py
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
|
-
from lusid.extensions.api_client_builder import build_client
|
|
2
1
|
from lusid.extensions.api_client_factory import SyncApiClientFactory, ApiClientFactory
|
|
3
2
|
from lusid.extensions.configuration_loaders import (
|
|
4
3
|
ConfigurationLoader,
|
|
5
4
|
SecretsFileConfigurationLoader,
|
|
6
5
|
EnvironmentVariablesConfigurationLoader,
|
|
7
6
|
ArgsConfigurationLoader,
|
|
8
|
-
get_api_configuration,
|
|
9
7
|
)
|
|
10
|
-
from lusid.extensions.api_configuration import ApiConfiguration
|
|
11
|
-
from lusid.extensions.retry import RetryingRestWrapper, RetryingRestWrapperAsync
|
|
12
|
-
from lusid.extensions.proxy_config import ProxyConfig
|
|
13
|
-
from lusid.extensions.refreshing_token import RefreshingToken
|
|
14
8
|
from lusid.extensions.api_client import SyncApiClient
|
|
15
|
-
|
|
9
|
+
|
|
10
|
+
__all__ = [
|
|
11
|
+
"SyncApiClientFactory",
|
|
12
|
+
"ApiClientFactory",
|
|
13
|
+
"ConfigurationLoader",
|
|
14
|
+
"SecretsFileConfigurationLoader",
|
|
15
|
+
"EnvironmentVariablesConfigurationLoader",
|
|
16
|
+
"ArgsConfigurationLoader",
|
|
17
|
+
"SyncApiClient"
|
|
18
|
+
]
|
lusid/extensions/api_client.py
CHANGED
|
@@ -213,6 +213,8 @@ class SyncApiClient:
|
|
|
213
213
|
url += "?" + url_query
|
|
214
214
|
|
|
215
215
|
try:
|
|
216
|
+
# if returning http_data_only then we need to deserialise response.
|
|
217
|
+
_preload_content = True if _return_http_data_only else _preload_content
|
|
216
218
|
# perform request and return response
|
|
217
219
|
response_data = self.request(
|
|
218
220
|
method, url,
|
|
@@ -543,7 +545,7 @@ class SyncApiClient:
|
|
|
543
545
|
if k in collection_formats:
|
|
544
546
|
collection_format = collection_formats[k]
|
|
545
547
|
if collection_format == 'multi':
|
|
546
|
-
new_params.extend((k, value) for value in v)
|
|
548
|
+
new_params.extend((k, quote(str(value))) for value in v)
|
|
547
549
|
else:
|
|
548
550
|
if collection_format == 'ssv':
|
|
549
551
|
delimiter = ' '
|
|
@@ -1,51 +1,117 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
|
+
from lusid.api_client import ApiClient
|
|
3
|
+
from lusid.extensions.retry import (
|
|
4
|
+
RetryingRestWrapper,
|
|
5
|
+
RetryingRestWrapperAsync
|
|
6
|
+
)
|
|
7
|
+
from lusid.extensions.api_client import SyncApiClient
|
|
2
8
|
from lusid.extensions.configuration_loaders import (
|
|
3
9
|
ConfigurationLoader,
|
|
4
10
|
default_config_loaders,
|
|
11
|
+
get_api_configuration
|
|
12
|
+
)
|
|
13
|
+
from lusid.extensions.socket_keep_alive import keep_alive_socket_options
|
|
14
|
+
from lusid.extensions.tcp_keep_alive_connector import (
|
|
15
|
+
TcpKeepAliveConnector,
|
|
16
|
+
TCPKeepAliveHTTPConnectionPool,
|
|
17
|
+
TCPKeepAliveHTTPSConnectionPool,
|
|
5
18
|
)
|
|
6
|
-
from
|
|
7
|
-
from lusid.extensions.configuration_loaders import get_api_configuration
|
|
19
|
+
from aiohttp import ClientSession
|
|
8
20
|
import logging
|
|
9
|
-
from typing import TypeVar, Type, Iterable
|
|
21
|
+
from typing import Any, Callable, Optional, Tuple, TypeVar, Type, Iterable, Union
|
|
22
|
+
import os
|
|
23
|
+
from requests import Response
|
|
10
24
|
|
|
11
25
|
logger = logging.getLogger(__name__)
|
|
12
26
|
|
|
13
27
|
T = TypeVar("T")
|
|
14
28
|
|
|
15
29
|
|
|
30
|
+
def set_additional_api_client_headers(
|
|
31
|
+
api_client: Union[ApiClient, SyncApiClient],
|
|
32
|
+
app_name: Optional[str] = None,
|
|
33
|
+
correlation_id: Optional[str] = None,
|
|
34
|
+
) -> None:
|
|
35
|
+
"""Sets additional headers for additional debugging info in LUSID
|
|
36
|
+
|
|
37
|
+
Parameters
|
|
38
|
+
----------
|
|
39
|
+
api_client : Union[ApiClient, SyncApiClient]
|
|
40
|
+
api client to set headers on
|
|
41
|
+
app_name : Optional[str], optional
|
|
42
|
+
name of the application in LUSID, by default None
|
|
43
|
+
correlation_id : Optional[str], optional
|
|
44
|
+
correlation id to track requests in LUSID, by default None
|
|
45
|
+
"""
|
|
46
|
+
try:
|
|
47
|
+
# set the application name if specified
|
|
48
|
+
if app_name is not None:
|
|
49
|
+
api_client.set_default_header("X-LUSID-Application", app_name)
|
|
50
|
+
|
|
51
|
+
# set a correlation id for all requests initiated with this ApiClient
|
|
52
|
+
corr_id = correlation_id or os.getenv("FBN_CORRELATION_ID")
|
|
53
|
+
if corr_id is not None:
|
|
54
|
+
api_client.set_default_header("CorrelationId", corr_id)
|
|
55
|
+
except AttributeError:
|
|
56
|
+
logger.exception("api_client must be either an ApiClient or a SyncApiClient")
|
|
57
|
+
raise
|
|
58
|
+
|
|
59
|
+
|
|
16
60
|
class SyncApiClientFactory:
|
|
17
61
|
def __init__(
|
|
18
62
|
self,
|
|
19
63
|
config_loaders: Iterable[ConfigurationLoader] = default_config_loaders,
|
|
20
|
-
id_provider_response_handler=None,
|
|
21
|
-
tcp_keep_alive=
|
|
22
|
-
|
|
23
|
-
|
|
64
|
+
id_provider_response_handler: Callable[[Response], None] = None,
|
|
65
|
+
tcp_keep_alive: bool = True,
|
|
66
|
+
socket_options: Optional[
|
|
67
|
+
Union[Tuple[Any, Any, Any], Tuple[Any, Any, None, int]]
|
|
68
|
+
] = keep_alive_socket_options(),
|
|
69
|
+
correlation_id: Optional[str] = None,
|
|
70
|
+
app_name: Optional[str] = None,
|
|
24
71
|
):
|
|
25
|
-
"""Create an ApiClientFactory which can build
|
|
72
|
+
"""Create an ApiClientFactory which can build
|
|
73
|
+
api objects with a configured ApiClient object
|
|
26
74
|
|
|
27
75
|
Parameters
|
|
28
76
|
----------
|
|
29
77
|
config_loaders : Iterable[ConfigurationLoader], optional
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
78
|
+
An Iterable of ConfigurationLoaders we can load configuration from.
|
|
79
|
+
Config settings are updated by each loader (last write wins),
|
|
80
|
+
by default default_config_loaders,
|
|
81
|
+
by default default_config_loaders
|
|
82
|
+
id_provider_response_handler : Callable[[Response], None], optional
|
|
83
|
+
A function that is called when a response is received from the token_url,
|
|
84
|
+
by default None
|
|
85
|
+
tcp_keep_alive : bool, optional
|
|
86
|
+
Should ApiClient be configured to send tcp keep alives, by default True
|
|
87
|
+
socket_options : Optional[ Union[Tuple[Any, Any, Any], Tuple[Any, Any, None, int]] ], optional
|
|
88
|
+
Set of socket options that should be applied to each connection,
|
|
89
|
+
by default keep_alive_socket_options
|
|
90
|
+
correlation_id : Optional[str], optional
|
|
91
|
+
A correlation ID that can be sent with each request, by default None
|
|
92
|
+
app_name : Optional[str], optional
|
|
93
|
+
The name of the application in LUSID, by default None
|
|
40
94
|
"""
|
|
41
95
|
api_config = get_api_configuration(config_loaders=config_loaders)
|
|
42
|
-
|
|
43
|
-
api_config,
|
|
44
|
-
build_async_client=False,
|
|
45
|
-
id_provider_response_handler=id_provider_response_handler,
|
|
96
|
+
api_client_config = api_config.build_api_client_config(
|
|
46
97
|
tcp_keep_alive=tcp_keep_alive,
|
|
47
|
-
|
|
48
|
-
|
|
98
|
+
socket_options=socket_options,
|
|
99
|
+
id_provider_response_handler=id_provider_response_handler
|
|
100
|
+
)
|
|
101
|
+
self.__api_client = SyncApiClient(
|
|
102
|
+
configuration=api_client_config,
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
rest_client_wrapper = RetryingRestWrapper
|
|
106
|
+
rc = self.__api_client.rest_client
|
|
107
|
+
if tcp_keep_alive:
|
|
108
|
+
rc.pool_manager.pool_classes_by_scheme = {"http": TCPKeepAliveHTTPConnectionPool, "https": TCPKeepAliveHTTPSConnectionPool}
|
|
109
|
+
|
|
110
|
+
wrapped_rest_client = rest_client_wrapper(rc)
|
|
111
|
+
self.__api_client.rest_client = wrapped_rest_client
|
|
112
|
+
|
|
113
|
+
set_additional_api_client_headers(
|
|
114
|
+
self.__api_client, app_name=app_name, correlation_id=correlation_id
|
|
49
115
|
)
|
|
50
116
|
|
|
51
117
|
def __enter__(self):
|
|
@@ -79,35 +145,80 @@ class ApiClientFactory:
|
|
|
79
145
|
def __init__(
|
|
80
146
|
self,
|
|
81
147
|
config_loaders: Iterable[ConfigurationLoader] = default_config_loaders,
|
|
82
|
-
id_provider_response_handler=None,
|
|
83
|
-
tcp_keep_alive=
|
|
84
|
-
|
|
85
|
-
|
|
148
|
+
id_provider_response_handler: Callable[[Response], None] = None,
|
|
149
|
+
tcp_keep_alive: bool = True,
|
|
150
|
+
socket_options: Optional[
|
|
151
|
+
Union[Tuple[Any, Any, Any], Tuple[Any, Any, None, int]]
|
|
152
|
+
] = keep_alive_socket_options(),
|
|
153
|
+
correlation_id: Optional[str] = None,
|
|
154
|
+
app_name: Optional[str] = None,
|
|
155
|
+
client_session: Optional[ClientSession] = None,
|
|
156
|
+
trace_configs: Optional[List[TraceConfig]] = None
|
|
86
157
|
):
|
|
87
|
-
"""Create an ApiClientFactory which can build api
|
|
158
|
+
"""Create an ApiClientFactory which can build api
|
|
159
|
+
objects with a configured ApiClient object
|
|
88
160
|
|
|
89
161
|
Parameters
|
|
90
162
|
----------
|
|
91
163
|
config_loaders : Iterable[ConfigurationLoader], optional
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
164
|
+
An Iterable of ConfigurationLoaders we can load configuration from.
|
|
165
|
+
Config settings are updated by each loader (last write wins),
|
|
166
|
+
by default default_config_loaders
|
|
167
|
+
id_provider_response_handler : Callable[[Response], None], optional
|
|
168
|
+
A function that is called when a response is received from the token_url,
|
|
169
|
+
by default None
|
|
170
|
+
tcp_keep_alive : bool, optional
|
|
171
|
+
Should ApiClient be configured to send tcp keep alives, by default True
|
|
172
|
+
socket_options : Optional[ Union[Tuple[Any, Any, Any], Tuple[Any, Any, None, int]] ], optional
|
|
173
|
+
Set of socket options that should be applied to each connection,
|
|
174
|
+
by default keep_alive_socket_options
|
|
175
|
+
correlation_id : Optional[str], optional
|
|
176
|
+
A correlation ID that can be sent with each request, by default None
|
|
177
|
+
app_name : Optional[str], optional
|
|
178
|
+
The name of the application in LUSID, by default None
|
|
179
|
+
client_session : Optional[ClientSession], optional
|
|
180
|
+
An aiohttp.ClientSession, pass this to re-use
|
|
181
|
+
connections across different ApiFactories,
|
|
182
|
+
by default None
|
|
183
|
+
trace_configs: Optional[List[TraceConfig]], optional
|
|
184
|
+
A list of aiohttp TraceConfigs, used to set up request tracing.
|
|
185
|
+
by default None
|
|
102
186
|
"""
|
|
103
187
|
api_config = get_api_configuration(config_loaders=config_loaders)
|
|
104
|
-
|
|
105
|
-
api_config,
|
|
106
|
-
build_async_client=True,
|
|
107
|
-
id_provider_response_handler=id_provider_response_handler,
|
|
188
|
+
api_client_config = api_config.build_api_client_config(
|
|
108
189
|
tcp_keep_alive=tcp_keep_alive,
|
|
109
|
-
|
|
110
|
-
|
|
190
|
+
socket_options=socket_options,
|
|
191
|
+
id_provider_response_handler=id_provider_response_handler
|
|
192
|
+
)
|
|
193
|
+
self.__api_client = ApiClient(
|
|
194
|
+
configuration=api_client_config,
|
|
195
|
+
)
|
|
196
|
+
rc = self.__api_client.rest_client
|
|
197
|
+
try:
|
|
198
|
+
if client_session is not None:
|
|
199
|
+
connector = client_session.connector
|
|
200
|
+
# by default take explicitly passed trace_config param
|
|
201
|
+
# otherwise copy from session.
|
|
202
|
+
trace_configs = trace_configs or client_session.trace_configs
|
|
203
|
+
else:
|
|
204
|
+
connector = rc.pool_manager.connector
|
|
205
|
+
if tcp_keep_alive:
|
|
206
|
+
connector = TcpKeepAliveConnector(connector=connector, socket_options=socket_options)
|
|
207
|
+
# dereference connector so existing session closes correctly
|
|
208
|
+
rc.pool_manager._connector = None
|
|
209
|
+
rc.pool_manager = ClientSession(
|
|
210
|
+
connector=connector,
|
|
211
|
+
trust_env=True,
|
|
212
|
+
trace_configs=trace_configs
|
|
213
|
+
)
|
|
214
|
+
except AttributeError:
|
|
215
|
+
logger.exception("client_session must be an aiohttp.ClientSession"
|
|
216
|
+
" object with an initialised TCP Connector")
|
|
217
|
+
rest_client_wrapper = RetryingRestWrapperAsync
|
|
218
|
+
wrapped_rest_client = rest_client_wrapper(rc)
|
|
219
|
+
self.__api_client.rest_client = wrapped_rest_client
|
|
220
|
+
set_additional_api_client_headers(
|
|
221
|
+
self.__api_client, app_name=app_name, correlation_id=correlation_id
|
|
111
222
|
)
|
|
112
223
|
|
|
113
224
|
async def __aenter__(self):
|
|
@@ -1,10 +1,28 @@
|
|
|
1
1
|
import re
|
|
2
|
+
import logging
|
|
3
|
+
from typing import Optional, Union, Tuple, Any, Callable
|
|
4
|
+
from lusid.configuration import Configuration
|
|
5
|
+
from lusid.extensions.refreshing_token import RefreshingToken
|
|
6
|
+
from lusid.extensions.socket_keep_alive import keep_alive_socket_options
|
|
7
|
+
from lusid.extensions.proxy_config import ProxyConfig
|
|
8
|
+
from requests import Response
|
|
9
|
+
logger = logging.getLogger(__name__)
|
|
2
10
|
|
|
3
11
|
|
|
4
12
|
class ApiConfiguration:
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
13
|
+
def __init__(
|
|
14
|
+
self,
|
|
15
|
+
token_url=None,
|
|
16
|
+
api_url=None,
|
|
17
|
+
username=None,
|
|
18
|
+
password=None,
|
|
19
|
+
client_id=None,
|
|
20
|
+
client_secret=None,
|
|
21
|
+
app_name=None,
|
|
22
|
+
certificate_filename=None,
|
|
23
|
+
proxy_config:Optional[ProxyConfig]=None,
|
|
24
|
+
access_token=None,
|
|
25
|
+
):
|
|
8
26
|
"""
|
|
9
27
|
The configuration required to access LUSID, read more at https://support.finbourne.com/getting-started-with-apis-sdks
|
|
10
28
|
|
|
@@ -42,12 +60,19 @@ class ApiConfiguration:
|
|
|
42
60
|
:param url: The url to format
|
|
43
61
|
:return: An Okta token url (if the input is an Okta issuer url). The original url otherwise.
|
|
44
62
|
"""
|
|
45
|
-
if (
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
63
|
+
if (
|
|
64
|
+
url is not None
|
|
65
|
+
and
|
|
66
|
+
# and it's an Okta oauth2 URL
|
|
67
|
+
re.search(
|
|
68
|
+
r"^http(s)?:\/\/.*\.okta\.com\/oauth2\/.+", url, flags=re.IGNORECASE
|
|
69
|
+
)
|
|
70
|
+
is not None
|
|
71
|
+
and
|
|
72
|
+
# and it's missing the token suffix
|
|
73
|
+
re.search(r"\/v\d+\/token$", url, flags=re.IGNORECASE) is None
|
|
74
|
+
):
|
|
75
|
+
return url.rstrip("/") + "/v1/token"
|
|
51
76
|
return url
|
|
52
77
|
|
|
53
78
|
self.__token_url = format_token_url(value)
|
|
@@ -116,10 +141,94 @@ class ApiConfiguration:
|
|
|
116
141
|
def proxy_config(self, value):
|
|
117
142
|
self.__proxy_config = value
|
|
118
143
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
144
|
+
def __setattr__(self, name, value):
|
|
145
|
+
if name == "access_token":
|
|
146
|
+
self.__access_token = value
|
|
147
|
+
super(ApiConfiguration, self).__setattr__(name, value)
|
|
148
|
+
|
|
149
|
+
def get_access_token(
|
|
150
|
+
self, id_provider_response_handler: Callable[[Response], None] = None
|
|
151
|
+
) -> Union[str, RefreshingToken]:
|
|
152
|
+
"""Gets either the set personal access token, or a RefreshingToken using OIDC parameters
|
|
122
153
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
154
|
+
Returns
|
|
155
|
+
-------
|
|
156
|
+
Union[str, RefreshingToken]
|
|
157
|
+
Token that can be used to authenticate to LUSID
|
|
158
|
+
|
|
159
|
+
"""
|
|
160
|
+
try:
|
|
161
|
+
if self.__access_token is not None:
|
|
162
|
+
return self.__access_token
|
|
163
|
+
logger.debug(
|
|
164
|
+
"Access token not provided, \
|
|
165
|
+
will attempt to set up client using OIDC parameters"
|
|
166
|
+
)
|
|
167
|
+
return RefreshingToken(
|
|
168
|
+
api_configuration=self,
|
|
169
|
+
id_provider_response_handler=id_provider_response_handler,
|
|
170
|
+
)
|
|
171
|
+
except AttributeError:
|
|
172
|
+
logger.exception(
|
|
173
|
+
"Could not retrieve access token - "
|
|
174
|
+
"ensure api_config is an ApiConfiguration object"
|
|
175
|
+
)
|
|
176
|
+
raise
|
|
177
|
+
except ValueError:
|
|
178
|
+
logger.exception(
|
|
179
|
+
"Could not retrieve access token - "
|
|
180
|
+
"ensure fields required to authenticate are set"
|
|
181
|
+
)
|
|
182
|
+
raise
|
|
183
|
+
|
|
184
|
+
def build_api_client_config(
|
|
185
|
+
self,
|
|
186
|
+
tcp_keep_alive: bool = True,
|
|
187
|
+
socket_options: Optional[
|
|
188
|
+
Union[Tuple[Any, Any, Any], Tuple[Any, Any, None, int]]
|
|
189
|
+
] = keep_alive_socket_options(),
|
|
190
|
+
id_provider_response_handler: Optional[Callable[[Response], None]] = None,
|
|
191
|
+
) -> Configuration:
|
|
192
|
+
"""Builds lusid.Configuration for initialising an api client.
|
|
193
|
+
|
|
194
|
+
Parameters
|
|
195
|
+
----------
|
|
196
|
+
tcp_keep_alive : bool, optional
|
|
197
|
+
Should socket options for tcp keep alive pings be set, by default True
|
|
198
|
+
socket_options : Optional[ Union[Tuple[Any, Any, Any], Tuple[Any, Any, None, int]] ], optional
|
|
199
|
+
A set of custom options to configure on connections, by default keep_alive_socket_options()
|
|
200
|
+
id_provider_response_handler : Optional[Callable[[Response], None]], optional
|
|
201
|
+
A function to run on response from the identity provider, by default None
|
|
202
|
+
|
|
203
|
+
Returns
|
|
204
|
+
-------
|
|
205
|
+
Configuration
|
|
206
|
+
config which can be used to initialise an api client
|
|
207
|
+
"""
|
|
208
|
+
access_token = self.get_access_token(
|
|
209
|
+
id_provider_response_handler=id_provider_response_handler
|
|
210
|
+
)
|
|
211
|
+
try:
|
|
212
|
+
if self.api_url is None:
|
|
213
|
+
logger.error("Api Url must have a value")
|
|
214
|
+
raise ValueError("Api Url must have a value")
|
|
215
|
+
if access_token is None:
|
|
216
|
+
logger.error("Access token must have a value")
|
|
217
|
+
raise ValueError("Access token must have a value")
|
|
218
|
+
config = Configuration(
|
|
219
|
+
access_token=access_token,
|
|
220
|
+
host=self.api_url,
|
|
221
|
+
ssl_ca_cert=self.certificate_filename,
|
|
222
|
+
)
|
|
223
|
+
if tcp_keep_alive:
|
|
224
|
+
config.socket_options = socket_options or keep_alive_socket_options()
|
|
225
|
+
# Set the proxy for lusid if needed
|
|
226
|
+
if self.proxy_config is not None:
|
|
227
|
+
config.proxy = self.proxy_config.address
|
|
228
|
+
config.proxy_headers = self.proxy_config.headers
|
|
229
|
+
return config
|
|
230
|
+
except (AttributeError, ValueError):
|
|
231
|
+
logger.exception(
|
|
232
|
+
"Unable to build api client, required configuration not provided"
|
|
233
|
+
)
|
|
234
|
+
raise
|
|
@@ -24,7 +24,7 @@ ENVIRONMENT_CONFIG_KEYS = {
|
|
|
24
24
|
|
|
25
25
|
SECRETS_FILE_CONFIG_KEYS = {
|
|
26
26
|
"token_url": "tokenUrl",
|
|
27
|
-
"api_url": "
|
|
27
|
+
"api_url": "lusidUrl",
|
|
28
28
|
"username": "username",
|
|
29
29
|
"password": "password",
|
|
30
30
|
"client_id": "clientId",
|
|
@@ -191,9 +191,7 @@ def get_api_configuration(config_loaders: Iterable[ConfigurationLoader]) -> ApiC
|
|
|
191
191
|
proxy_username = config.pop("proxy_username", None)
|
|
192
192
|
proxy_password = config.pop("proxy_password", None)
|
|
193
193
|
# If the proxy address is missing ensure that no proxy is used in the ApiConfiguration
|
|
194
|
-
if
|
|
195
|
-
(item is not None for item in (proxy_address, proxy_password, proxy_username))
|
|
196
|
-
):
|
|
194
|
+
if proxy_address is not None:
|
|
197
195
|
config["proxy_config"] = ProxyConfig(
|
|
198
196
|
address=proxy_address, username=proxy_username, password=proxy_password
|
|
199
197
|
)
|
lusid/extensions/proxy_config.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from urllib3 import make_headers
|
|
2
|
-
from typing import
|
|
2
|
+
from typing import Dict
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
class ProxyConfig:
|
|
@@ -56,7 +56,7 @@ class ProxyConfig:
|
|
|
56
56
|
return {"http": proxy_url, "https": proxy_url}
|
|
57
57
|
|
|
58
58
|
@property
|
|
59
|
-
def headers(self) ->
|
|
59
|
+
def headers(self) -> Dict[str, str]:
|
|
60
60
|
"""Return Proxy auth headers
|
|
61
61
|
|
|
62
62
|
Returns
|
|
@@ -64,6 +64,9 @@ class ProxyConfig:
|
|
|
64
64
|
Any
|
|
65
65
|
Proxy auth headers
|
|
66
66
|
"""
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
67
|
+
if self.__username is not None and self.__password is not None:
|
|
68
|
+
return make_headers(
|
|
69
|
+
proxy_basic_auth=f"{self.__username}:{self.__password}"
|
|
70
|
+
)
|
|
71
|
+
else:
|
|
72
|
+
return {}
|
|
@@ -5,6 +5,15 @@ from urllib3.connection import HTTPConnection
|
|
|
5
5
|
|
|
6
6
|
__logger__ = logging.getLogger(__name__)
|
|
7
7
|
|
|
8
|
+
# The content to send on Mac OS in the TCP Keep Alive probe
|
|
9
|
+
TCP_KEEPALIVE = 0x10
|
|
10
|
+
# The maximum time to keep the connection idle before sending probes
|
|
11
|
+
TCP_KEEP_IDLE = 60
|
|
12
|
+
# The interval between probes
|
|
13
|
+
TCP_KEEPALIVE_INTERVAL = 60
|
|
14
|
+
# The maximum number of failed probes before terminating the connection
|
|
15
|
+
TCP_KEEP_CNT = 3
|
|
16
|
+
|
|
8
17
|
|
|
9
18
|
def keep_alive_socket_options() -> Sequence:
|
|
10
19
|
"""Returns default socket options for all platforms for
|
|
@@ -15,15 +24,6 @@ def keep_alive_socket_options() -> Sequence:
|
|
|
15
24
|
Sequence
|
|
16
25
|
Set of socket options.
|
|
17
26
|
"""
|
|
18
|
-
# The content to send on Mac OS in the TCP Keep Alive probe
|
|
19
|
-
TCP_KEEPALIVE = 0x10
|
|
20
|
-
# The maximum time to keep the connection idle before sending probes
|
|
21
|
-
TCP_KEEP_IDLE = 60
|
|
22
|
-
# The interval between probes
|
|
23
|
-
TCP_KEEPALIVE_INTERVAL = 60
|
|
24
|
-
# The maximum number of failed probes before terminating the connection
|
|
25
|
-
TCP_KEEP_CNT = 3
|
|
26
|
-
|
|
27
27
|
try:
|
|
28
28
|
# linux and some windows runtimes
|
|
29
29
|
return HTTPConnection.default_socket_options + [
|
|
@@ -35,18 +35,17 @@ def keep_alive_socket_options() -> Sequence:
|
|
|
35
35
|
except AttributeError:
|
|
36
36
|
pass
|
|
37
37
|
try:
|
|
38
|
-
#
|
|
38
|
+
# darwin
|
|
39
39
|
return HTTPConnection.default_socket_options + [
|
|
40
|
-
socket.
|
|
41
|
-
(
|
|
40
|
+
(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1),
|
|
41
|
+
(socket.IPPROTO_TCP, TCP_KEEPALIVE, TCP_KEEPALIVE_INTERVAL),
|
|
42
42
|
]
|
|
43
43
|
except AttributeError:
|
|
44
44
|
pass
|
|
45
45
|
try:
|
|
46
|
-
#
|
|
46
|
+
# windows
|
|
47
47
|
return HTTPConnection.default_socket_options + [
|
|
48
|
-
(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
|
|
49
|
-
(socket.IPPROTO_TCP, TCP_KEEPALIVE, TCP_KEEPALIVE_INTERVAL),
|
|
48
|
+
(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
|
|
50
49
|
]
|
|
51
50
|
except AttributeError:
|
|
52
51
|
__logger__.exception("Unable to set TCP Keep-alive socket options")
|