def test_string(self): """ string is converted to unicode """ self.assertEqual(lenient_ascii_text("test"), u"test")
class GroupState(object): """ Object that represents the state :ivar tenant_id: the tenant ID of the scaling group whose state this object represents :type: :obj:`six.text_type` :ivar group_id: the ID of the scaling group whose state this object represents :type: :obj:`six.text_type` :ivar group_name: the name of the scaling group whose state this object represents :type: :obj:`six.text_type` :ivar dict active: the mapping of active server ids and their info :ivar dict pending: the list of pending job ids and their info :ivar group_touched: timezone-aware ISO860 formatted timestamp that represents when the last time any policy was executed on the group. Could be None. :type: :obj:`six.text_type` :ivar dict policy_touched: dictionary mapping policy ids to the last time they were executed, if ever. The time is stored as ISO860 format str :ivar bool paused: whether the scaling group is paused in scaling activities :ivar bool suspended: Is the scaling group suspended due to account suspension? :ivar status: Status of the group. One of :obj:`ScalingGroupStatus` members :type: :obj:`NamedConstant` :ivar list error_reasons: List of string-based reasons why this group is in ERROR. Not needed when group is ACTIVE :ivar int desired: the desired capacity of the scaling group :ivar callable now: callable that returns a :class:`bytes` timestamp used for testing purposes. Defaults to :func:`timestamp.now` """ tenant_id = attr.ib(validator=aiof(six.text_type), convert=lenient_ascii_text) group_id = attr.ib(validator=aiof(six.text_type), convert=lenient_ascii_text) group_name = attr.ib(validator=aiof(six.text_type), convert=lenient_ascii_text) active = attr.ib(validator=aiof(dict)) pending = attr.ib(validator=aiof(dict)) group_touched = attr.ib( validator=aiof(six.text_type), convert=lambda t: lenient_ascii_text(t or timestamp.MIN)) policy_touched = attr.ib(validator=aiof(dict)) paused = attr.ib(validator=aiof(bool)) status = attr.ib(validator=aiof(NamedConstant)) suspended = attr.ib(validator=aiof(bool), default=False) error_reasons = attr.ib(convert=tuple, default=[]) desired = attr.ib(validator=aiof(int), default=0) now = attr.ib(default=timestamp.now) def remove_job(self, job_id): """ Removes a pending job from the pending list. If the job is not in pending, raises an AssertionError. :param bytes job_id: the id of the job to complete :returns: :data:`None` :raises AssertionError: if the job doesn't exist """ assert job_id in self.pending, "Job doesn't exist: {0}".format(job_id) del self.pending[job_id] def add_job(self, job_id): """ Adds a pending job to the pending collection. If the job is already in pending, raises an AssertError. :param bytes job_id: the id of the job to complete :returns: :data:`None` :raises AssertionError: if the job already exists """ assert job_id not in self.pending, "Job exists: {0}".format(job_id) self.pending[job_id] = {'created': self.now()} def add_active(self, server_id, server_info): """ Adds a server to the collection of active servers. Adds a creation time if there isn't one. :param bytes job_id: the id of the job to complete :param dict server_info: a dictionary containing relevant server info. TBD: What's in server_info ultimately - currently: name, url :returns: :data:`None` :raises AssertionError: if the server id already exists """ assert server_id not in self.active, "Server already exists: {}".format( server_id) server_info.setdefault('created', self.now()) self.active[server_id] = server_info def remove_active(self, server_id): """ Removes a server to the collection of active servers. :param bytes server_id: the id of the server to delete :raises AssertionError: if the server id does not exist """ assert server_id in self.active, "Server does not exist: {}".format( server_id) del self.active[server_id] def mark_executed(self, policy_id): """ Record the execution time (now) of a particular policy. This also updates the group touched time. :param bytes policy_id: the id of the policy that was executed :returns: :data:`None` """ self.policy_touched[policy_id] = self.group_touched = self.now() def get_capacity(self): """ Get the capacities for a group. :return: A dictionary with the desired_capcity, current_capacity, and pending_capacity. """ return { 'current_capacity': len(self.active), 'pending_capacity': len(self.pending), 'desired_capacity': len(self.active) + len(self.pending) }
def test_unicode(self): """ unicode is returned as such """ self.assertEqual(lenient_ascii_text(u"test"), u"test")