Repository: boto/boto3
File: boto3/resources/factory.py (Python)

Code before:
            attrs[subresource.name] = self._create_class_partial(
                name, subresource, service_name, resource_name, model,
                resource_defs, service_model)


    def _load_waiters(self, attrs, model):
        """
        Load resource waiters from the model. Each waiter allows you to
        wait until a resource reaches a specific state by polling the state
        of the resource.
        """
        for waiter in model.waiters:
            attrs[waiter.name] = self._create_waiter(waiter)

    def _create_identifier(factory_self, name):
        """
        Creates a read-only property for identifier attributes.
        """
        def identifier(self):
            return getattr(self, '_' + name, None)

        identifier.__name__ = str(name)
        identifier.__doc__ = 'TODO'
        return property(identifier)

    def _create_autoload_property(factory_self, name, snake_cased):
        """
        Creates a new property on the resource to lazy-load its value
        via the resource's ``load`` method (if it exists).
        """
        # The property loader will check to see if this resource has already
        # been loaded and return the cached value if possible. If not, then
        # it first checks to see if it CAN be loaded (raise if not), then
        # calls the load before returning the value.
        def property_loader(self):
            if self.meta.data is None:
                if hasattr(self, 'load'):
                    self.load()
                else:
                    raise ResourceLoadException(
                        '{0} has no load method'.format(self.__class__.__name__))

            return self.meta.data.get(name)

        property_loader.__name__ = str(snake_cased)
        property_loader.__doc__ = 'TODO'
        return property(property_loader)

    def _create_waiter(factory_self, waiter_model):
        """
        Creates a new wait method for each resource where both a waiter and

Review comment (suggestion):
Scratch what I said, I remembered why I set it a default to `None`. It is because when the resource is instantiated there is check to make sure that all of the identifiers are non-`None` values: https://github.com/boto/boto3/blob/develop/boto3/resources/base.py#L117. So if I did not use a default, I would get a bad error message like: `'test.Queue' object has no attribute '_url'` instead of the current message of: `ValueError: Required parameter url not set` because the identifier getter is called before the ValueError is thrown. I would prefer to keep it as is unless you have any other suggestions.


Code after:
            attrs[subresource.name] = self._create_class_partial(
                name, subresource, service_name, resource_name, model,
                resource_defs, service_model)


    def _load_waiters(self, attrs, model):
        """
        Load resource waiters from the model. Each waiter allows you to
        wait until a resource reaches a specific state by polling the state
        of the resource.
        """
        for waiter in model.waiters:
            attrs[waiter.name] = self._create_waiter(waiter)

    def _create_identifier(factory_self, name):
        """
        Creates a read-only property for identifier attributes.
        """
        def identifier(self):
            # The default value is set to ``None`` instead of
            # raising an AttributeError because when resources are
            # instantiated a check is made such that none of the
            # identifiers have a value ``None``. If any are ``None``,
            # a more informative user error than a generic AttributeError
            # is raised.
            return getattr(self, '_' + name, None)

        identifier.__name__ = str(name)
        identifier.__doc__ = 'TODO'
        return property(identifier)

    def _create_autoload_property(factory_self, name, snake_cased):
        """
        Creates a new property on the resource to lazy-load its value
        via the resource's ``load`` method (if it exists).
        """
        # The property loader will check to see if this resource has already
        # been loaded and return the cached value if possible. If not, then
        # it first checks to see if it CAN be loaded (raise if not), then
        # calls the load before returning the value.
        def property_loader(self):
            if self.meta.data is None:
                if hasattr(self, 'load'):
                    self.load()
                else:
                    raise ResourceLoadException(
                        '{0} has no load method'.format(self.__class__.__name__))

            return self.meta.data.get(name)

        property_loader.__name__ = str(snake_cased)