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)), ])
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) return skeleton
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=(',', ':'))
def _build_structure(self, model, shapes): members = OrderedDict() shape = self._build_initial_shape(model) shape['members'] = members for name, member_model in model['members'].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
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 handle_op_renames(new_model, enhancements): # This allows for operations to be renamed. The only # implemented transformation is removing part of the operation name # (because that's all we currently need.) remove = enhancements.get('transformations', {}).get( 'operation-name', {}).get('remove') if remove is not None: # We're going to recreate the dictionary because we want to preserve # the order. This is the only option we have unless we have our own # custom OrderedDict. remove_regex = re.compile(remove) operations = new_model['operations'] new_operation = OrderedDict() for key in operations: new_key = remove_regex.sub('', key) new_operation[new_key] = operations[key] new_model['operations'] = new_operation
def build_model(self): """Build the model based on the provided members. :rtype: kscore.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 handle_remove_deprecated_params(new_model, enhancements): # This removes any parameter whose documentation string contains # the specified phrase that marks a deprecated parameter. keyword = enhancements.get('transformations', {}).get( 'remove-deprecated-params', {}).get('deprecated_keyword') if keyword is not None: operations = new_model['operations'] for op_name in operations: operation = operations[op_name] params = operation.get('input', {}).get('members') if params: new_params = OrderedDict() for param_name in params: param = params[param_name] docs = param['documentation'] if docs and docs.find(keyword) >= 0: continue new_params[param_name] = param operation['input']['members'] = new_params
def load_file(self, file_path): """Attempt to load the file path. :type file_path: str :param file_path: The full path to the file to load without the '.json' extension. :return: The loaded data if it exists, otherwise None. """ full_path = file_path + '.yaml' if not os.path.isfile(full_path): return # By default the file will be opened with locale encoding on Python 3. # We specify "utf8" here to ensure the correct behavior. with open(full_path, 'rb') as fp: payload = fp.read().decode('utf-8') return OrderedDict(yaml.load(payload))
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 = []
def remove_all_sections(self): self._structure = OrderedDict()
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 kscore 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>')) kscore_pagination_params = [ DocumentedShape( name='PaginationConfig', type_name='structure', documentation=( '<p>A dictionary that provides parameters to control ' 'pagination.</p>'), members=pagination_config_members) ] kscore_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=kscore_pagination_params, include_output=kscore_pagination_response_params, exclude_input=service_pagination_params, exclude_output=service_pagination_response_params, include_signature=include_signature)
class Config(object): """Advanced configuration for KSCore 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 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. * '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 """ 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), ('s3', 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) 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 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: kscore.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 __init__(self, name=None): self.members = OrderedDict() self._name_generator = ShapeNameGenerator() if name is None: self.name = self._name_generator.new_shape_name('structure')