示例#1
0
    def _build_structure(self, model, shapes):
        members = OrderedDict()
        shape = self._build_initial_shape(model)
        shape['members'] = members

        for name, member_model in model.get('members', OrderedDict()).items():
            member_shape_name = self._get_shape_name(member_model)
            members[name] = {'shape': member_shape_name}
            self._build_model(member_model, shapes, member_shape_name)
        return shape
示例#2
0
 def setUp(self):
     super(TestDocumentSharedExamples, self).setUp()
     self.add_shape({"foo": {"type": "string"}})
     self.add_shape({"nested": {"type": "string"}})
     self.add_shape({
         "other": {
             "type": "structure",
             "members": {
                 "nested": {
                     "shape": "nested"
                 }
             }
         }
     })
     self.add_shape(
         {"aloha": {
             "type": "list",
             "member": {
                 "shape": "other"
             }
         }})
     self.add_shape_to_params('foo', 'foo')
     self.add_shape_to_params('aloha', 'aloha')
     self._examples = [{
         "id":
         "sample-id",
         "title":
         "sample-title",
         "description":
         "Sample Description.",
         "input":
         OrderedDict([
             ("aloha", ["other", {
                 "nested": "fun!"
             }]),
             ("foo", "bar"),
         ]),
         "output":
         OrderedDict([
             ("foo", "baz"),
         ]),
         "comments": {
             "input": {
                 "aloha": "mahalo"
             },
             "output": {
                 "foo": "Sample Comment"
             }
         }
     }]
示例#3
0
    def test_does_decode_template_body_in_order(self):
        expected_ordering = OrderedDict([('TemplateVersion', 1.0),
                                         ('APropertyOfSomeKind', 'a value'),
                                         ('list', [1, 2, 3]),
                                         ('nested',
                                          OrderedDict([('key', 'value'),
                                                       ('foo', 'bar')]))])
        template_string = json.dumps(expected_ordering)
        parsed_response = {'TemplateBody': template_string}

        handlers.json_decode_template_body(parsed=parsed_response)
        result = parsed_response['TemplateBody']

        self.assertTrue(isinstance(result, OrderedDict))
        for element, expected_element in zip(result, expected_ordering):
            self.assertEqual(element, expected_element)
示例#4
0
 def _generate_type_map(self, shape, stack):
     key_shape = shape.key
     value_shape = shape.value
     assert key_shape.type_name == 'string'
     return OrderedDict([
         ('KeyName', self._generate_skeleton(value_shape, stack)),
     ])
示例#5
0
 def _generate_type_structure(self, shape, stack):
     if stack.count(shape.name) > 1:
         return {}
     skeleton = OrderedDict()
     for member_name, member_shape in shape.members.items():
         skeleton[member_name] = self._generate_skeleton(
             member_shape, stack, name=member_name)
     return skeleton
示例#6
0
 def test_list_objects_unicode_query_string_eu_central_1(self):
     self.region_name = 'eu-central-1'
     params = OrderedDict([('Bucket', 'safename'),
                           ('Marker', u'\xe4\xf6\xfc-01.txt')])
     prepared_request = self.get_prepared_request('list_objects', params)
     self.assertEqual(prepared_request.url,
                      ('https://safename.s3.eu-central-1.amazonaws.com/'
                       '?marker=%C3%A4%C3%B6%C3%BC-01.txt'))
    def build_policy(self,
                     resource,
                     date_less_than,
                     date_greater_than=None,
                     ip_address=None):
        """A helper to build policy.

        :type resource: str
        :param resource: The URL or the stream filename of the protected object

        :type date_less_than: datetime
        :param date_less_than: The URL will expire after the time has passed

        :type date_greater_than: datetime
        :param date_greater_than: The URL will not be valid until this time

        :type ip_address: str
        :param ip_address: Use 'x.x.x.x' for an IP, or 'x.x.x.x/x' for a subnet

        :rtype: str
        :return: The policy in a compact string.
        """
        # Note:
        # 1. Order in canned policy is significant. Special care has been taken
        #    to ensure the output will match the order defined by the document.
        #    There is also a test case to ensure that order.
        #    SEE: http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-creating-signed-url-canned-policy.html#private-content-canned-policy-creating-policy-statement
        # 2. Albeit the order in custom policy is not required by CloudFront,
        #    we still use OrderedDict internally to ensure the result is stable
        #    and also matches canned policy requirement.
        #    SEE: http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-creating-signed-url-custom-policy.html
        moment = int(datetime2timestamp(date_less_than))
        condition = OrderedDict({"DateLessThan": {"AWS:EpochTime": moment}})
        if ip_address:
            if '/' not in ip_address:
                ip_address += '/32'
            condition["IpAddress"] = {"AWS:SourceIp": ip_address}
        if date_greater_than:
            moment = int(datetime2timestamp(date_greater_than))
            condition["DateGreaterThan"] = {"AWS:EpochTime": moment}
        ordered_payload = [('Resource', resource), ('Condition', condition)]
        custom_policy = {"Statement": [OrderedDict(ordered_payload)]}
        return json.dumps(custom_policy, separators=(',', ':'))
示例#8
0
 def __init__(self, resource):
     self._resource = resource
     self._client = self._resource.meta.client
     self._resource_model = self._resource.meta.resource_model
     self._service_model = self._client.meta.service_model
     self._resource_name = self._resource.meta.resource_model.name
     self._service_name = self._service_model.service_name
     self._service_docs_name = self._client.__class__.__name__
     self.member_map = OrderedDict()
     self.represents_service_resource = (
         self._service_name == self._resource_name)
    def test_ordered_shape_builder(self):
        b = model.DenormalizedStructureBuilder()
        shape = b.with_members(
            OrderedDict([('A', {
                'type': 'string'
            }),
                         ('B', {
                             'type':
                             'structure',
                             'members':
                             OrderedDict([('C', {
                                 'type': 'string'
                             }), ('D', {
                                 'type': 'string'
                             })])
                         })])).build_model()

        # Members should be in order
        self.assertEqual(['A', 'B'], list(shape.members.keys()))

        # Nested structure members should *also* stay ordered
        self.assertEqual(['C', 'D'], list(shape.members['B'].members.keys()))
示例#10
0
    def __init__(self, name, section_names=None, target='man', context=None):
        """Provides a Hierarichial structure to a ReSTDocument

        You can write to it similiar to as you can to a ReSTDocument but
        has an innate structure for more orginaztion and abstraction.

        :param name: The name of the document
        :param section_names: A list of sections to be included
            in the document.
        :param target: The target documentation of the Document structure
        :param context: A dictionary of data to store with the strucuture. These
            are only stored per section not the entire structure.
        """
        super(DocumentStructure, self).__init__(target=target)
        self._name = name
        self._structure = OrderedDict()
        self._path = [self._name]
        self._context = {}
        if context is not None:
            self._context = context
        if section_names is not None:
            self._generate_structure(section_names)
    def build_model(self):
        """Build the model based on the provided members.

        :rtype: ibm_botocore.model.StructureShape
        :return: The built StructureShape object.

        """
        shapes = OrderedDict()
        denormalized = {
            'type': 'structure',
            'members': self._members,
        }
        self._build_model(denormalized, shapes, self.name)
        resolver = ShapeResolver(shape_map=shapes)
        return StructureShape(shape_name=self.name,
                              shape_model=shapes[self.name],
                              shape_resolver=resolver)
    def _setup_models(self):
        self.json_model = {
            'metadata': {
                'apiVersion': '2014-01-01',
                'endpointPrefix': 'myservice',
                'signatureVersion': 'v4',
                'serviceFullName': 'AWS MyService',
                'uid': 'myservice-2014-01-01',
                'protocol': 'query'
            },
            'operations': {
                'SampleOperation': {
                    'name': 'SampleOperation',
                    'input': {
                        'shape': 'SampleOperationInputOutput'
                    },
                    'output': {
                        'shape': 'SampleOperationInputOutput'
                    }
                }
            },
            'shapes': {
                'SampleOperationInputOutput': {
                    'type': 'structure',
                    'members': OrderedDict()
                },
                'String': {
                    'type': 'string'
                }
            }
        }

        self.waiter_json_model = {
            "version": 2,
            "waiters": {
                "SampleOperationComplete": {
                    "delay":
                    15,
                    "operation":
                    "SampleOperation",
                    "maxAttempts":
                    40,
                    "acceptors": [{
                        "expected": "complete",
                        "matcher": "pathAll",
                        "state": "success",
                        "argument": "Biz"
                    }, {
                        "expected": "failed",
                        "matcher": "pathAny",
                        "state": "failure",
                        "argument": "Biz"
                    }]
                }
            }
        }

        self.paginator_json_model = {
            "pagination": {
                "SampleOperation": {
                    "input_token": "NextResult",
                    "output_token": "NextResult",
                    "limit_key": "MaxResults",
                    "result_key": "Biz"
                }
            }
        }

        self.example_json_model = {
            "version": 1,
            "examples": {
                "SampleOperation": [{
                    "id": "sample-id",
                    "title": "sample-title",
                    "description": "Sample Description.",
                    "input": OrderedDict([
                        ("Biz", "foo"),
                    ]),
                    "comments": {
                        "input": {
                            "Biz": "bar"
                        },
                    }
                }]
            }
        }
示例#13
0
 def remove_all_sections(self):
     self._structure = OrderedDict()
 def __init__(self, name=None):
     self.members = OrderedDict()
     self._name_generator = ShapeNameGenerator()
     if name is None:
         self.name = self._name_generator.new_shape_name('structure')
示例#15
0
    def _setup_models(self):
        self.json_model = {
            'metadata': {
                'apiVersion': '2014-01-01',
                'endpointPrefix': 'myservice',
                'signatureVersion': 'v4',
                'serviceFullName': 'AWS MyService',
                'protocol': 'query',
                'serviceId': 'MyService',
            },
            'operations': {
                'SampleOperation': {
                    'name': 'SampleOperation',
                    'input': {
                        'shape': 'SampleOperationInputOutput'
                    },
                    'output': {
                        'shape': 'SampleOperationInputOutput'
                    }
                }
            },
            'shapes': {
                'SampleOperationInputOutput': {
                    'type':
                    'structure',
                    'members':
                    OrderedDict([
                        ('Foo', {
                            'shape': 'String',
                            'documentation': 'Documents Foo'
                        }),
                        ('Bar', {
                            'shape': 'String',
                            'documentation': 'Documents Bar'
                        }),
                    ])
                },
                'String': {
                    'type': 'string'
                }
            }
        }

        self.example_json_model = {
            "version": 1,
            "examples": {
                "SampleOperation": [{
                    "id": "sample-id",
                    "title": "sample-title",
                    "description": "Sample Description.",
                    "input": OrderedDict([
                        ("Foo", "bar"),
                    ]),
                    "comments": {
                        "input": {
                            "Foo": "biz"
                        },
                    }
                }]
            }
        }

        self.waiter_json_model = {
            "version": 2,
            "waiters": {
                "SampleOperationComplete": {
                    "delay":
                    15,
                    "operation":
                    "SampleOperation",
                    "maxAttempts":
                    40,
                    "acceptors": [{
                        "expected": "complete",
                        "matcher": "pathAll",
                        "state": "success",
                        "argument": "Biz"
                    }, {
                        "expected": "failed",
                        "matcher": "pathAny",
                        "state": "failure",
                        "argument": "Biz"
                    }]
                }
            }
        }

        self.paginator_json_model = {
            "pagination": {
                "SampleOperation": {
                    "input_token": "NextResult",
                    "output_token": "NextResult",
                    "limit_key": "MaxResults",
                    "result_key": "Biz"
                }
            }
        }

        self.resource_json_model = {
            "service": {
                "actions":
                OrderedDict([("SampleOperation", {
                    "request": {
                        "operation": "SampleOperation"
                    }
                }),
                             ("SampleListReturnOperation", {
                                 "request": {
                                     "operation": "SampleOperation"
                                 },
                                 "resource": {
                                     "type":
                                     "Sample",
                                     "identifiers": [{
                                         "target": "Name",
                                         "source": "response",
                                         "path": "Samples[].Name"
                                     }],
                                     "path":
                                     "Samples[]"
                                 }
                             })]),
                "has": {
                    "Sample": {
                        "resource": {
                            "type": "Sample",
                            "identifiers": [{
                                "target": "Name",
                                "source": "input"
                            }]
                        }
                    }
                },
                "hasMany": {
                    "Samples": {
                        "request": {
                            "operation": "SampleOperation"
                        },
                        "resource": {
                            "type":
                            "Sample",
                            "identifiers": [{
                                "target": "Name",
                                "source": "response",
                                "path": "Samples[].Foo"
                            }]
                        }
                    }
                }
            },
            "resources": {
                "Sample": {
                    "identifiers": [{
                        "name": "Name",
                        "memberName": "Foo"
                    }],
                    "shape": "SampleOperationInputOutput",
                    "load": {
                        "request": {
                            "operation":
                            "SampleOperation",
                            "params": [{
                                "target": "Foo",
                                "source": "identifier",
                                "name": "Name"
                            }]
                        }
                    },
                    "actions": {
                        "Operate": {
                            "request": {
                                "operation":
                                "SampleOperation",
                                "params": [{
                                    "target": "Foo",
                                    "source": "identifier",
                                    "name": "Name"
                                }]
                            }
                        }
                    },
                    "batchActions": {
                        "Operate": {
                            "request": {
                                "operation":
                                "SampleOperation",
                                "params": [{
                                    "target": "Samples[].Foo",
                                    "source": "identifier",
                                    "name": "Name"
                                }]
                            }
                        }
                    },
                    "has": {
                        "RelatedSample": {
                            "resource": {
                                "type":
                                "Sample",
                                "identifiers": [{
                                    "target": "Name",
                                    "source": "data",
                                    "path": "Foo"
                                }]
                            }
                        }
                    },
                    "waiters": {
                        "Complete": {
                            "waiterName":
                            "SampleOperationComplete",
                            "params": [{
                                "target": "Foo",
                                "source": "identifier",
                                "name": "Name"
                            }]
                        }
                    }
                }
            }
        }
示例#16
0
class Config(object):
    """Advanced configuration for Botocore clients.

    :type region_name: str
    :param region_name: The region to use in instantiating the client

    :type signature_version: str
    :param signature_version: The signature version when signing requests.

    :type user_agent: str
    :param user_agent: The value to use in the User-Agent header.

    :type user_agent_extra: str
    :param user_agent_extra: The value to append to the current User-Agent
        header value.

    :type connect_timeout: float or int
    :param connect_timeout: The time in seconds till a timeout exception is
        thrown when attempting to make a connection. The default is 60
        seconds.

    :type read_timeout: float or int
    :param read_timeout: The time in seconds till a timeout exception is
        thrown when attempting to read from a connection. The default is
        60 seconds.

    :type parameter_validation: bool
    :param parameter_validation: Whether parameter validation should occur
        when serializing requests. The default is True.  You can disable
        parameter validation for performance reasons.  Otherwise, it's
        recommended to leave parameter validation enabled.

    :type max_pool_connections: int
    :param max_pool_connections: The maximum number of connections to
        keep in a connection pool.  If this value is not set, the default
        value of 10 is used.

    :type proxies: dict
    :param proxies: A dictionary of proxy servers to use by protocol or
        endpoint, e.g.:
        {'http': 'foo.bar:3128', 'http://hostname': 'foo.bar:4012'}.
        The proxies are used on each request.

    :type s3: dict
    :param s3: A dictionary of s3 specific configurations.
        Valid keys are:

        * 'use_accelerate_endpoint' -- Refers to whether to use the S3
          Accelerate endpoint. The value must be a boolean. If True, the
          client will use the S3 Accelerate endpoint. If the S3 Accelerate
          endpoint is being used then the addressing style will always
          be virtual.

        * 'payload_signing_enabled' -- Refers to whether or not to SHA256
          sign sigv4 payloads. By default, this is disabled for streaming
          uploads (UploadPart and PutObject).

        * 'addressing_style' -- Refers to the style in which to address
          s3 endpoints. Values must be a string that equals:

          * auto -- Addressing style is chosen for user. Depending
            on the configuration of client, the endpoint may be addressed in
            the virtual or the path style. Note that this is the default
            behavior if no style is specified.

          * virtual -- Addressing style is always virtual. The name of the
            bucket must be DNS compatible or an exception will be thrown.
            Endpoints will be addressed as such: mybucket.s3.amazonaws.com

          * path -- Addressing style is always by path. Endpoints will be
            addressed as such: s3.amazonaws.com/mybucket

        * 'us_east_1_regional_endpoint' - Refers to what S3 endpoint to use
          when the region is configured to be us-east-1. Values must be a
          string that equals:

           * regional -- Use the us-east-1.amazonaws.com endpoint if the
             client is configured to use the us-east-1 region.

           * legacy -- Use the s3.amazonaws.com endpoint if the client is
             configured to use the us-east-1 region. This is the default if
             the configuration option is not specified.


    :type retries: dict
    :param retries: A dictionary for retry specific configurations.
        Valid keys are:

        * 'total_max_attempts' -- An integer representing the maximum number of
          total attempts that will be made on a single request.  This includes
          the initial request, so a value of 1 indicates that no requests
          will be retried.  If ``total_max_attempts`` and ``max_attempts``
          are both provided, ``total_max_attempts`` takes precedence.
          ``total_max_attempts`` is preferred over ``max_attempts`` because
          it maps to the ``AWS_MAX_ATTEMPTS`` environment variable and
          the ``max_attempts`` config file value.
        * 'max_attempts' -- An integer representing the maximum number of
          retry attempts that will be made on a single request. For
          example, setting this value to 2 will result in the request
          being retried at most two times after the initial request. Setting
          this value to 0 will result in no retries ever being attempted on
          the initial request. If not provided, the number of retries will
          default to whatever is modeled, which is typically four retries.
        * 'mode' -- A string representing the type of retry mode ibm_botocore
          should use.  Valid values are:
              * ``legacy`` - The pre-existing retry behavior.
              * ``standard`` - The standardized set of retry rules.  This
                will also default to 3 max attempts unless overridden.
              * ``adaptive`` - Retries with additional client side throttling.

    :type client_cert: str, (str, str)
    :param client_cert: The path to a certificate for TLS client authentication.

        When a str is provided it is treated as a path to a client certificate
        to be used when creating a TLS connection.

        If a client key is to be provided alongside the client certificate the
        client_cert should be set to a tuple of length two where the first
        element is the path to the client certificate and the second element is
        the path to the certificate key.

    :type inject_host_prefix: bool
    :param inject_host_prefix: Whether host prefix injection should occur.

        Defaults to True.

        Setting this to False disables the injection of operation parameters
        into the prefix of the hostname. This is useful for clients providing
        custom endpoints that should not have their host prefix modified.
    """
    OPTION_DEFAULTS = OrderedDict([
        ('region_name', None),
        ('signature_version', None),
        ('user_agent', None),
        ('user_agent_extra', None),
        ('connect_timeout', DEFAULT_TIMEOUT),
        ('read_timeout', DEFAULT_TIMEOUT),
        ('parameter_validation', True),
        ('max_pool_connections', MAX_POOL_CONNECTIONS),
        ('proxies', None),
        ('s3', None),
        ('retries', None),
        ('client_cert', None),
        ('inject_host_prefix', True),
        ('endpoint_discovery_enabled', None),
    ])

    def __init__(self, *args, **kwargs):
        self._user_provided_options = self._record_user_provided_options(
            args, kwargs)

        # Merge the user_provided options onto the default options
        config_vars = copy.copy(self.OPTION_DEFAULTS)
        config_vars.update(self._user_provided_options)

        # Set the attributes based on the config_vars
        for key, value in config_vars.items():
            setattr(self, key, value)

        # Validate the s3 options
        self._validate_s3_configuration(self.s3)

        self._validate_retry_configuration(self.retries)

    def _record_user_provided_options(self, args, kwargs):
        option_order = list(self.OPTION_DEFAULTS)
        user_provided_options = {}

        # Iterate through the kwargs passed through to the constructor and
        # map valid keys to the dictionary
        for key, value in kwargs.items():
            if key in self.OPTION_DEFAULTS:
                user_provided_options[key] = value
            # The key must exist in the available options
            else:
                raise TypeError('Got unexpected keyword argument \'%s\'' % key)

        # The number of args should not be longer than the allowed
        # options
        if len(args) > len(option_order):
            raise TypeError('Takes at most %s arguments (%s given)' %
                            (len(option_order), len(args)))

        # Iterate through the args passed through to the constructor and map
        # them to appropriate keys.
        for i, arg in enumerate(args):
            # If it a kwarg was specified for the arg, then error out
            if option_order[i] in user_provided_options:
                raise TypeError(
                    'Got multiple values for keyword argument \'%s\'' %
                    (option_order[i]))
            user_provided_options[option_order[i]] = arg

        return user_provided_options

    def _validate_s3_configuration(self, s3):
        if s3 is not None:
            addressing_style = s3.get('addressing_style')
            if addressing_style not in ['virtual', 'auto', 'path', None]:
                raise InvalidS3AddressingStyleError(
                    s3_addressing_style=addressing_style)

    def _validate_retry_configuration(self, retries):
        if retries is not None:
            for key, value in retries.items():
                if key not in ['max_attempts', 'mode', 'total_max_attempts']:
                    raise InvalidRetryConfigurationError(
                        retry_config_option=key)
                if key == 'max_attempts' and value < 0:
                    raise InvalidMaxRetryAttemptsError(
                        provided_max_attempts=value,
                        min_value=0,
                    )
                if key == 'total_max_attempts' and value < 1:
                    raise InvalidMaxRetryAttemptsError(
                        provided_max_attempts=value,
                        min_value=1,
                    )
                if key == 'mode' and value not in [
                        'legacy', 'standard', 'adaptive'
                ]:
                    raise InvalidRetryModeError(provided_retry_mode=value)

    def merge(self, other_config):
        """Merges the config object with another config object

        This will merge in all non-default values from the provided config
        and return a new config object

        :type other_config: ibm_botocore.config.Config
        :param other config: Another config object to merge with. The values
            in the provided config object will take precedence in the merging

        :returns: A config object built from the merged values of both
            config objects.
        """
        # Make a copy of the current attributes in the config object.
        config_options = copy.copy(self._user_provided_options)

        # Merge in the user provided options from the other config
        config_options.update(other_config._user_provided_options)

        # Return a new config object with the merged properties.
        return Config(**config_options)
def document_wait_method(section,
                         waiter_name,
                         event_emitter,
                         service_model,
                         service_waiter_model,
                         include_signature=True):
    """Documents a the wait method of a waiter

    :param section: The section to write to

    :param waiter_name: The name of the waiter

    :param event_emitter: The event emitter to use to emit events

    :param service_model: The service model

    :param service_waiter_model: The waiter model associated to the service

    :param include_signature: Whether or not to include the signature.
        It is useful for generating docstrings.
    """
    waiter_model = service_waiter_model.get_waiter(waiter_name)
    operation_model = service_model.operation_model(waiter_model.operation)

    waiter_config_members = OrderedDict()

    waiter_config_members['Delay'] = DocumentedShape(
        name='Delay',
        type_name='integer',
        documentation=('<p>The amount of time in seconds to wait between '
                       'attempts. Default: {0}</p>'.format(
                           waiter_model.delay)))

    waiter_config_members['MaxAttempts'] = DocumentedShape(
        name='MaxAttempts',
        type_name='integer',
        documentation=('<p>The maximum number of attempts to be made. '
                       'Default: {0}</p>'.format(waiter_model.max_attempts)))

    botocore_waiter_params = [
        DocumentedShape(
            name='WaiterConfig',
            type_name='structure',
            documentation=(
                '<p>A dictionary that provides parameters to control '
                'waiting behavior.</p>'),
            members=waiter_config_members)
    ]

    wait_description = (
        'Polls :py:meth:`{0}.Client.{1}` every {2} '
        'seconds until a successful state is reached. An error is '
        'returned after {3} failed checks.'.format(
            get_service_module_name(service_model),
            xform_name(waiter_model.operation), waiter_model.delay,
            waiter_model.max_attempts))

    document_model_driven_method(section,
                                 'wait',
                                 operation_model,
                                 event_emitter=event_emitter,
                                 method_description=wait_description,
                                 example_prefix='waiter.wait',
                                 include_input=botocore_waiter_params,
                                 document_output=False,
                                 include_signature=include_signature)
示例#18
0
class ClientExceptionsDocumenter(object):
    _USER_GUIDE_LINK = (
        'https://ibm_boto3.amazonaws.com/'
        'v1/documentation/api/latest/guide/error-handling.html')
    _GENERIC_ERROR_SHAPE = DocumentedShape(
        name='Error',
        type_name='structure',
        documentation=('Normalized access to common exception attributes.'),
        members=OrderedDict([
            ('Code',
             DocumentedShape(
                 name='Code',
                 type_name='string',
                 documentation=(
                     'An identifier specifying the exception type.'),
             )),
            ('Message',
             DocumentedShape(
                 name='Message',
                 type_name='string',
                 documentation=(
                     'A descriptive message explaining why the exception '
                     'occured.'),
             )),
        ]),
    )

    def __init__(self, client):
        self._client = client
        self._service_name = self._client.meta.service_model.service_name

    def document_exceptions(self, section):
        self._add_title(section)
        self._add_overview(section)
        self._add_exceptions_list(section)
        self._add_exception_classes(section)

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

    def _add_overview(self, section):
        section.style.new_line()
        section.write(
            'Client exceptions are available on a client instance '
            'via the ``exceptions`` property. For more detailed instructions '
            'and examples on the exact usage of client exceptions, see the '
            'error handling ')
        section.style.external_link(
            title='user guide',
            link=self._USER_GUIDE_LINK,
        )
        section.write('.')
        section.style.new_line()

    def _exception_class_name(self, shape):
        cls_name = self._client.__class__.__name__
        return '%s.Client.exceptions.%s' % (cls_name, shape.name)

    def _add_exceptions_list(self, section):
        error_shapes = self._client.meta.service_model.error_shapes
        if not error_shapes:
            section.style.new_line()
            section.write('This client has no modeled exception classes.')
            section.style.new_line()
            return
        section.style.new_line()
        section.write('The available client exceptions are:')
        section.style.new_line()
        for shape in error_shapes:
            class_name = self._exception_class_name(shape)
            section.style.li(':py:class:`%s`' % class_name)

    def _add_exception_classes(self, section):
        for shape in self._client.meta.service_model.error_shapes:
            self._add_exception_class(section, shape)

    def _add_exception_class(self, section, shape):
        class_section = section.add_new_section(shape.name)
        class_name = self._exception_class_name(shape)
        class_section.style.start_sphinx_py_class(class_name=class_name)
        self._add_top_level_documentation(class_section, shape)
        self._add_exception_catch_example(class_section, shape)
        self._add_response_attr(class_section, shape)
        class_section.style.end_sphinx_py_class()

    def _add_top_level_documentation(self, section, shape):
        if shape.documentation:
            section.style.new_line()
            section.include_doc_string(shape.documentation)
            section.style.new_line()

    def _add_exception_catch_example(self, section, shape):
        section.style.new_line()
        section.style.bold('Example')
        section.style.start_codeblock()
        section.write('try:')
        section.style.indent()
        section.style.new_line()
        section.write('...')
        section.style.dedent()
        section.style.new_line()
        section.write('except client.exceptions.%s as e:' % shape.name)
        section.style.indent()
        section.style.new_line()
        section.write('print(e.response)')
        section.style.dedent()
        section.style.end_codeblock()

    def _add_response_attr(self, section, shape):
        response_section = section.add_new_section('response')
        response_section.style.start_sphinx_py_attr('response')
        self._add_response_attr_description(response_section)
        self._add_response_example(response_section, shape)
        self._add_response_params(response_section, shape)
        response_section.style.end_sphinx_py_attr()

    def _add_response_attr_description(self, section):
        section.style.new_line()
        section.include_doc_string(
            'The parsed error response. All exceptions have a top level '
            '``Error`` key that provides normalized access to common '
            'exception atrributes. All other keys are specific to this '
            'service or exception class.')
        section.style.new_line()

    def _add_response_example(self, section, shape):
        example_section = section.add_new_section('syntax')
        example_section.style.new_line()
        example_section.style.bold('Syntax')
        example_section.style.new_paragraph()
        documenter = ResponseExampleDocumenter(
            service_name=self._service_name,
            operation_name=None,
            event_emitter=self._client.meta.events,
        )
        documenter.document_example(
            example_section,
            shape,
            include=[self._GENERIC_ERROR_SHAPE],
        )

    def _add_response_params(self, section, shape):
        params_section = section.add_new_section('Structure')
        params_section.style.new_line()
        params_section.style.bold('Structure')
        params_section.style.new_paragraph()
        documenter = ResponseParamsDocumenter(
            service_name=self._service_name,
            operation_name=None,
            event_emitter=self._client.meta.events,
        )
        documenter.document_params(
            params_section,
            shape,
            include=[self._GENERIC_ERROR_SHAPE],
        )
示例#19
0
class Config(object):
    """Advanced configuration for Botocore clients.

    :type region_name: str
    :param region_name: The region to use in instantiating the client

    :type signature_version: str
    :param signature_version: The signature version when signing requests.

    :type user_agent: str
    :param user_agent: The value to use in the User-Agent header.

    :type user_agent_extra: str
    :param user_agent_extra: The value to append to the current User-Agent
        header value.

    :type connect_timeout: int
    :param connect_timeout: The time in seconds till a timeout exception is
        thrown when attempting to make a connection. The default is 60
        seconds.

    :type read_timeout: int
    :param read_timeout: The time in seconds till a timeout exception is
        thrown when attempting to read from a connection. The default is
        60 seconds.

    :type parameter_validation: bool
    :param parameter_validation: Whether parameter validation should occur
        when serializing requests. The default is True.  You can disable
        parameter validation for performance reasons.  Otherwise, it's
        recommended to leave parameter validation enabled.

    :type max_pool_connections: int
    :param max_pool_connections: The maximum number of connections to
        keep in a connection pool.  If this value is not set, the default
        value of 10 is used.

    :type s3: dict
    :param s3: A dictionary of s3 specific configurations.
        Valid keys are:

        * 'use_accelerate_endpoint' -- Refers to whether to use the S3
          Accelerate endpoint. The value must be a boolean. If True, the
          client will use the S3 Accelerate endpoint. If the S3 Accelerate
          endpoint is being used then the addressing style will always
          be virtual.

        * 'payload_signing_enabled' -- Refers to whether or not to SHA256
          sign sigv4 payloads. By default, this is disabled for streaming
          uploads (UploadPart and PutObject).

        * 'addressing_style' -- Refers to the style in which to address
          s3 endpoints. Values must be a string that equals:

          * auto -- Addressing style is chosen for user. Depending
            on the configuration of client, the endpoint may be addressed in
            the virtual or the path style. Note that this is the default
            behavior if no style is specified.

          * virtual -- Addressing style is always virtual. The name of the
            bucket must be DNS compatible or an exception will be thrown.
            Endpoints will be addressed as such: mybucket.s3.amazonaws.com

          * path -- Addressing style is always by path. Endpoints will be
            addressed as such: s3.amazonaws.com/mybucket

    :type retries: dict
    :param retries: A dictionary for retry specific configurations.
        Valid keys are:

        * 'max_attempts' -- An integer representing the maximum number of
          retry attempts that will be made on a single request. For
          example, setting this value to 2 will result in the request
          being retried at most two times after the initial request. Setting
          this value to 0 will result in no retries ever being attempted on
          the initial request. If not provided, the number of retries will
          default to whatever is modeled, which is typically four retries.
    """
    OPTION_DEFAULTS = OrderedDict([('region_name', None),
                                   ('signature_version', None),
                                   ('user_agent', None),
                                   ('user_agent_extra', None),
                                   ('connect_timeout', DEFAULT_TIMEOUT),
                                   ('read_timeout', DEFAULT_TIMEOUT),
                                   ('parameter_validation', True),
                                   ('max_pool_connections',
                                    MAX_POOL_CONNECTIONS), ('s3', None),
                                   ('retries', None)])

    def __init__(self, *args, **kwargs):
        self._user_provided_options = self._record_user_provided_options(
            args, kwargs)

        # Merge the user_provided options onto the default options
        config_vars = copy.copy(self.OPTION_DEFAULTS)
        config_vars.update(self._user_provided_options)

        # Set the attributes based on the config_vars
        for key, value in config_vars.items():
            setattr(self, key, value)

        # Validate the s3 options
        self._validate_s3_configuration(self.s3)

        self._validate_retry_configuration(self.retries)

    def _record_user_provided_options(self, args, kwargs):
        option_order = list(self.OPTION_DEFAULTS)
        user_provided_options = {}

        # Iterate through the kwargs passed through to the constructor and
        # map valid keys to the dictionary
        for key, value in kwargs.items():
            if key in self.OPTION_DEFAULTS:
                user_provided_options[key] = value
            # The key must exist in the available options
            else:
                raise TypeError('Got unexpected keyword argument \'%s\'' % key)

        # The number of args should not be longer than the allowed
        # options
        if len(args) > len(option_order):
            raise TypeError('Takes at most %s arguments (%s given)' %
                            (len(option_order), len(args)))

        # Iterate through the args passed through to the constructor and map
        # them to appropriate keys.
        for i, arg in enumerate(args):
            # If it a kwarg was specified for the arg, then error out
            if option_order[i] in user_provided_options:
                raise TypeError(
                    'Got multiple values for keyword argument \'%s\'' %
                    (option_order[i]))
            user_provided_options[option_order[i]] = arg

        return user_provided_options

    def _validate_s3_configuration(self, s3):
        if s3 is not None:
            addressing_style = s3.get('addressing_style')
            if addressing_style not in ['virtual', 'auto', 'path', None]:
                raise InvalidS3AddressingStyleError(
                    s3_addressing_style=addressing_style)

    def _validate_retry_configuration(self, retries):
        if retries is not None:
            for key in retries:
                if key not in ['max_attempts']:
                    raise InvalidRetryConfigurationError(
                        retry_config_option=key)
                if key == 'max_attempts' and retries[key] < 0:
                    raise InvalidMaxRetryAttemptsError(
                        provided_max_attempts=retries[key])

    def merge(self, other_config):
        """Merges the config object with another config object

        This will merge in all non-default values from the provided config
        and return a new config object

        :type other_config: ibm_botocore.config.Config
        :param other config: Another config object to merge with. The values
            in the provided config object will take precedence in the merging

        :returns: A config object built from the merged values of both
            config objects.
        """
        # Make a copy of the current attributes in the config object.
        config_options = copy.copy(self._user_provided_options)

        # Merge in the user provided options from the other config
        config_options.update(other_config._user_provided_options)

        # Return a new config object with the merged properties.
        return Config(**config_options)
示例#20
0
def document_paginate_method(section,
                             paginator_name,
                             event_emitter,
                             service_model,
                             paginator_config,
                             include_signature=True):
    """Documents the paginate method of a paginator

    :param section: The section to write to

    :param paginator_name: The name of the paginator. It is snake cased.

    :param event_emitter: The event emitter to use to emit events

    :param service_model: The service model

    :param paginator_config: The paginator config associated to a particular
        paginator.

    :param include_signature: Whether or not to include the signature.
        It is useful for generating docstrings.
    """
    # Retrieve the operation model of the underlying operation.
    operation_model = service_model.operation_model(paginator_name)

    # Add representations of the request and response parameters
    # we want to include in the description of the paginate method.
    # These are parameters we expose via the ibm_botocore interface.
    pagination_config_members = OrderedDict()

    pagination_config_members['MaxItems'] = DocumentedShape(
        name='MaxItems',
        type_name='integer',
        documentation=('<p>The total number of items to return. If the total '
                       'number of items available is more than the value '
                       'specified in max-items then a <code>NextToken</code> '
                       'will be provided in the output that you can use to '
                       'resume pagination.</p>'))

    pagination_config_members['PageSize'] = DocumentedShape(
        name='PageSize',
        type_name='integer',
        documentation='<p>The size of each page.<p>')

    pagination_config_members['StartingToken'] = DocumentedShape(
        name='StartingToken',
        type_name='string',
        documentation=('<p>A token to specify where to start paginating. '
                       'This is the <code>NextToken</code> from a previous '
                       'response.</p>'))

    botocore_pagination_params = [
        DocumentedShape(
            name='PaginationConfig',
            type_name='structure',
            documentation=(
                '<p>A dictionary that provides parameters to control '
                'pagination.</p>'),
            members=pagination_config_members)
    ]

    botocore_pagination_response_params = [
        DocumentedShape(name='NextToken',
                        type_name='string',
                        documentation=('<p>A token to resume pagination.</p>'))
    ]

    service_pagination_params = []

    # Add the normal input token of the method to a list
    # of input paramters that we wish to hide since we expose our own.
    if isinstance(paginator_config['input_token'], list):
        service_pagination_params += paginator_config['input_token']
    else:
        service_pagination_params.append(paginator_config['input_token'])

    # Hide the limit key in the documentation.
    if paginator_config.get('limit_key', None):
        service_pagination_params.append(paginator_config['limit_key'])

    # Hide the output tokens in the documentation.
    service_pagination_response_params = []
    if isinstance(paginator_config['output_token'], list):
        service_pagination_response_params += paginator_config['output_token']
    else:
        service_pagination_response_params.append(
            paginator_config['output_token'])

    paginate_description = (
        'Creates an iterator that will paginate through responses '
        'from :py:meth:`{0}.Client.{1}`.'.format(
            get_service_module_name(service_model),
            xform_name(paginator_name)))

    document_model_driven_method(
        section,
        'paginate',
        operation_model,
        event_emitter=event_emitter,
        method_description=paginate_description,
        example_prefix='response_iterator = paginator.paginate',
        include_input=botocore_pagination_params,
        include_output=botocore_pagination_response_params,
        exclude_input=service_pagination_params,
        exclude_output=service_pagination_response_params,
        include_signature=include_signature)
示例#21
0
class DocumentStructure(ReSTDocument):
    def __init__(self, name, section_names=None, target='man', context=None):
        """Provides a Hierarichial structure to a ReSTDocument

        You can write to it similiar to as you can to a ReSTDocument but
        has an innate structure for more orginaztion and abstraction.

        :param name: The name of the document
        :param section_names: A list of sections to be included
            in the document.
        :param target: The target documentation of the Document structure
        :param context: A dictionary of data to store with the strucuture. These
            are only stored per section not the entire structure.
        """
        super(DocumentStructure, self).__init__(target=target)
        self._name = name
        self._structure = OrderedDict()
        self._path = [self._name]
        self._context = {}
        if context is not None:
            self._context = context
        if section_names is not None:
            self._generate_structure(section_names)

    @property
    def name(self):
        """The name of the document structure"""
        return self._name

    @property
    def path(self):
        """
        A list of where to find a particular document structure in the
        overlying document structure.
        """
        return self._path

    @path.setter
    def path(self, value):
        self._path = value

    @property
    def available_sections(self):
        return list(self._structure)

    @property
    def context(self):
        return self._context

    def _generate_structure(self, section_names):
        for section_name in section_names:
            self.add_new_section(section_name)

    def add_new_section(self, name, context=None):
        """Adds a new section to the current document structure

        This document structure will be considered a section to the
        current document structure but will in itself be an entirely
        new document structure that can be written to and have sections
        as well

        :param name: The name of the section.
        :param context: A dictionary of data to store with the strucuture. These
            are only stored per section not the entire structure.
        :rtype: DocumentStructure
        :returns: A new document structure to add to but lives as a section
            to the document structure it was instantiated from.
        """
        # Add a new section
        section = self.__class__(name=name, target=self.target,
                                 context=context)
        section.path = self.path + [name]
        # Indent the section apporpriately as well
        section.style.indentation = self.style.indentation
        section.translation_map = self.translation_map
        section.hrefs = self.hrefs
        self._structure[name] = section
        return section

    def get_section(self, name):
        """Retrieve a section"""
        return self._structure[name]

    def delete_section(self, name):
        """Delete a section"""
        del self._structure[name]

    def flush_structure(self):
        """Flushes a doc structure to a ReSTructed string

        The document is flushed out in a DFS style where sections and their
        subsections' values are added to the string as they are visited.
        """
        # We are at the root flush the links at the beginning of the
        # document
        if len(self.path) == 1:
            if self.hrefs:
                self.style.new_paragraph()
                for refname, link in self.hrefs.items():
                    self.style.link_target_definition(refname, link)
        value = self.getvalue()
        for name, section in self._structure.items():
            value += section.flush_structure()
        return value

    def getvalue(self):
        return ''.join(self._writes).encode('utf-8')

    def remove_all_sections(self):
        self._structure = OrderedDict()

    def clear_text(self):
        self._writes = []