Example #1
0
    def _create_operation_method(factory_self, method_name, op_data):
        # Determine the correct name for the method.
        # This is because the method names will be standardized across
        # resources, so we'll have to lean on the ``api_name`` to figure out
        # what the correct underlying method name on the ``Connection`` should
        # be.
        # Map -> map -> unmap -> remap -> map :/
        conn_method_name = to_snake_case(op_data['api_name'])

        if not six.PY3:
            method_name = str(method_name)

        def _new_method(self, **kwargs):
            params = self.full_update_params(method_name, kwargs)
            method = getattr(self._connection, conn_method_name, None)

            if not method:
                msg = "Introspected method named '{0}' not available on " + \
                      "the connection."
                raise NoSuchMethod(msg.format(conn_method_name))

            result = method(**params)
            return self.full_post_process(method_name, result)

        _new_method.__name__ = method_name
        _new_method.__doc__ = DEFAULT_DOCSTRING
        return _new_method
Example #2
0
    def _update_docstrings(self):
        """
        Runs through the operation methods & updates their docstrings if
        necessary.

        If the method has the default placeholder docstring, this will replace
        it with the docstring from the underlying connection.
        """
        ops = self._details.collection_data['operations']

        for method_name in ops.keys():
            meth = getattr(self.__class__, method_name, None)

            if not meth:
                continue

            if meth.__doc__ != DEFAULT_DOCSTRING:
                # It already has a custom docstring. Leave it alone.
                continue

            # Needs updating. So there's at least *something* vaguely useful
            # there, use the docstring from the underlying ``Connection``
            # method.
            # FIXME: We need to figure out a way to make this more useful, if
            #        possible.
            api_name = ops[method_name]['api_name']
            conn_meth = getattr(self._connection, to_snake_case(api_name))

            # We need to do detection here, because Py2 treats ``.__doc__``
            # as a special read-only attribute. :/
            if six.PY3:
                meth.__doc__ = conn_meth.__doc__
            else:
                meth.__func__.__doc__ = conn_meth.__doc__
Example #3
0
    def post_process_get(self, result):
        """
        Given an object with identifiers, fetches the data for that object
        from the service.

        This alters the data on the object itself & simply passes through what
        was received.

        :param result: The response data
        :type result: dict

        :returns: The unmodified response data
        """
        if not hasattr(result, 'items'):
            # If it's not a dict, give up & just return whatever you get.
            return result

        # We need to possibly drill into the response & get out the data here.
        # Check for a result key.
        result_key = self._details.result_key_for('get')

        if not result_key:
            # There's no result_key. Just use the top-level data.
            data = result
        else:
            data = result[result_key]

        for key, value in data.items():
            self._data[to_snake_case(key)] = value

        return result
Example #4
0
    def __init__(self, api_name, name=None, required=True):
        super(BaseField, self).__init__()
        self.api_name = api_name
        # An optimization for dealing with botocore.
        # See ``boto3.core.resources.methods.BaseMethod.update_bound_params_from_api``
        # for details...
        self.snake_name = to_snake_case(api_name)
        self.required = required

        if name:
            self.name = name
Example #5
0
    def build_resource(self, data):
        """
        Given some data, builds the correct/matching ``Resource`` subclass
        for the ``Collection``. Useful in things like ``create`` & ``each``.

        :param result: The data for an instance handed back from the API.
        :type result: dict

        :returns: A ``Resource`` subclass
        """
        if self._res_class is None:
            self._res_class = self._details.session.get_resource(
                self._details.service_name,
                self._details.resource
            )

        final_data = {}

        # Lightly post-process the data, to look more Pythonic.
        for key, value in data.items():
            final_data[to_snake_case(key)] = value

        return self._res_class(connection=self._connection, **final_data)
Example #6
0
 def test_to_snake_case(self):
     self.assertEqual(to_snake_case('Create'), 'create')
     self.assertEqual(to_snake_case('CreateQueue'), 'create_queue')
     self.assertEqual(to_snake_case('ThisIsReallyLong'), 'this_is_really_long')
     self.assertEqual(to_snake_case('createQueue'), 'create_queue')
Example #7
0
 def test_to_snake_case(self):
     self.assertEqual(to_snake_case('Create'), 'create')
     self.assertEqual(to_snake_case('CreateQueue'), 'create_queue')
     self.assertEqual(to_snake_case('ThisIsReallyLong'),
                      'this_is_really_long')
     self.assertEqual(to_snake_case('createQueue'), 'create_queue')