Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add generic support for client context params #3037

Merged
merged 6 commits into from
Oct 24, 2023
Merged
Show file tree
Hide file tree
Changes from 4 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
19 changes: 11 additions & 8 deletions botocore/args.py
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ def compute_client_args(
disable_request_compression=(
client_config.disable_request_compression
),
client_context_params=client_config.client_context_params,
)
self._compute_retry_config(config_kwargs)
self._compute_connect_timeout(config_kwargs)
Expand Down Expand Up @@ -641,14 +642,16 @@ def _build_endpoint_resolver(
client_endpoint_url=endpoint_url,
legacy_endpoint_url=endpoint.host,
)
# botocore does not support client context parameters generically
# for every service. Instead, the s3 config section entries are
# available as client context parameters. In the future, endpoint
# rulesets of services other than s3/s3control may require client
# context parameters.
client_context = (
s3_config_raw if self._is_s3_service(service_name_raw) else {}
)
# Client context params for s3 conflict with the available settings
# in the `s3` parameter on the `Config` object. If the same parameter
# is set in both places, the value in the `s3` parameter takes priority.
if client_config is not None:
client_context = client_config.client_context_params or {}
else:
client_context = {}
if self._is_s3_service(service_name_raw):
client_context.update(s3_config_raw)

sig_version = (
client_config.signature_version
if client_config is not None
Expand Down
10 changes: 10 additions & 0 deletions botocore/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,15 @@ class Config:
:param disable_request_compression: Disables request body compression if
set to True.

Defaults to None.

:type client_context_params: dict
:param client_context_params: A dictionary of parameters specific to
individual services. If available, valid parameters can be found in the
``Client Context Parameters`` section of the service's client homepage.
dlm6693 marked this conversation as resolved.
Show resolved Hide resolved
Invalid parameters or ones that are not used by the specified service
will be ignored.

Defaults to None.
"""

Expand Down Expand Up @@ -247,6 +256,7 @@ class Config:
('tcp_keepalive', None),
('request_min_compression_size_bytes', None),
('disable_request_compression', None),
('client_context_params', None),
]
)

Expand Down
54 changes: 54 additions & 0 deletions botocore/docs/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
# language governing permissions and limitations under the License.
import os

from botocore import xform_name
from botocore.compat import OrderedDict
from botocore.docs.bcdoc.restdoc import DocumentStructure
from botocore.docs.example import ResponseExampleDocumenter
Expand Down Expand Up @@ -399,3 +400,56 @@ def _add_response_params(self, section, shape):
shape,
include=[self._GENERIC_ERROR_SHAPE],
)


class ClientContextParamsDocumenter:
_CONFIG_GUIDE_LINK = (
'https://boto3.amazonaws.com/'
'v1/documentation/api/latest/guide/configuration.html'
)
dlm6693 marked this conversation as resolved.
Show resolved Hide resolved

OMITTED_CONTEXT_PARAMS = {
's3': (
'Accelerate',
'DisableMultiRegionAccessPoints',
'ForcePathStyle',
'UseArnRegion',
),
's3control': ('UseArnRegion',),
}

def __init__(self, service_name, context_params):
self._service_name = service_name
self._context_params = context_params

def document_context_params(self, section):
self._add_title(section)
self._add_overview(section)
self._add_context_params_list(section)

def _add_title(self, section):
section.style.h2('Client Context Parameters')

def _add_overview(self, section):
section.style.new_line()
section.write(
'Client context parameters are configurable on a client '
'instance via the ``client_context_params`` parameter in the '
'``Config`` object. For more detailed instructions and examples '
'on the exact usage of context params see the '
)
section.style.external_link(
title='configuration guide',
link=self._CONFIG_GUIDE_LINK,
)
section.write('.')
section.style.new_line()

def _add_context_params_list(self, section):
section.style.new_line()
sn = f'``{self._service_name}``'
section.writeln(f'The available {sn} client context params are:')
for param in self._context_params:
section.style.new_line()
name = f'``{xform_name(param.name)}``'
section.write(f'* {name} ({param.type}) - {param.documentation}')
25 changes: 24 additions & 1 deletion botocore/docs/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@
# ANY KIND, either express or implied. See the License for the specific
# language governing permissions and limitations under the License.
from botocore.docs.bcdoc.restdoc import DocumentStructure
from botocore.docs.client import ClientDocumenter, ClientExceptionsDocumenter
from botocore.docs.client import (
ClientContextParamsDocumenter,
ClientDocumenter,
ClientExceptionsDocumenter,
)
from botocore.docs.paginator import PaginatorDocumenter
from botocore.docs.waiter import WaiterDocumenter
from botocore.exceptions import DataNotFoundError
Expand All @@ -37,6 +41,7 @@ def __init__(self, service_name, session, root_docs_path):
'client-exceptions',
'paginator-api',
'waiter-api',
'client-context-params',
]

def document_service(self):
Expand All @@ -52,6 +57,10 @@ def document_service(self):
self.client_exceptions(doc_structure.get_section('client-exceptions'))
self.paginator_api(doc_structure.get_section('paginator-api'))
self.waiter_api(doc_structure.get_section('waiter-api'))
context_params_section = doc_structure.get_section(
'client-context-params'
)
self.client_context_params(context_params_section)
return doc_structure.flush_structure()

def title(self, section):
Expand Down Expand Up @@ -108,3 +117,17 @@ def get_examples(self, service_name, api_version=None):
service_name, 'examples-1', api_version
)
return examples['examples']

def client_context_params(self, section):
omitted_params = ClientContextParamsDocumenter.OMITTED_CONTEXT_PARAMS
params_to_omit = omitted_params.get(self._service_name, [])
service_model = self._client.meta.service_model
raw_context_params = service_model.client_context_parameters
context_params = [
p for p in raw_context_params if p.name not in params_to_omit
]
if context_params:
context_param_documenter = ClientContextParamsDocumenter(
self._service_name, context_params
)
context_param_documenter.document_context_params(section)
22 changes: 22 additions & 0 deletions tests/functional/docs/test_s3.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
# ANY KIND, either express or implied. See the License for the specific
# language governing permissions and limitations under the License.
from botocore import xform_name
from botocore.docs.client import ClientContextParamsDocumenter
from botocore.docs.service import ServiceDocumenter
from tests.functional.docs import BaseDocsFunctionalTest

Expand Down Expand Up @@ -78,3 +80,23 @@ def test_copy_source_param_docs_also_modified(self):
self.assert_contains_line(
"You can also provide this value as a dictionary", param_docs
)

def test_s3_context_params_omitted(self):
omitted_params = ClientContextParamsDocumenter.OMITTED_CONTEXT_PARAMS
s3_omitted_params = omitted_params['s3']
content = ServiceDocumenter(
's3', self._session, self.root_services_path
).document_service()
for param in s3_omitted_params:
param_name = f'``{xform_name(param)}``'
self.assert_not_contains_line(param_name, content)

def test_s3control_context_params_omitted(self):
omitted_params = ClientContextParamsDocumenter.OMITTED_CONTEXT_PARAMS
s3control_omitted_params = omitted_params['s3control']
content = ServiceDocumenter(
's3control', self._session, self.root_services_path
).document_service()
for param in s3control_omitted_params:
param_name = f'``{xform_name(param)}``'
self.assert_not_contains_line(param_name, content)
Loading