From 41ba4699c6b3f636fb75eb27322e2dfa81f3313e Mon Sep 17 00:00:00 2001 From: Cory Johns Date: Fri, 9 Dec 2016 16:56:28 -0500 Subject: [PATCH] Minor improvements * Sleep a small amount in block_until to avoid CPU-heavy busy-wait * Better repr of ModelEntities for debugging * Better errors when statuses accessed on dead units and applications --- juju/application.py | 4 ++-- juju/model.py | 32 +++++++++++++++++++++++--------- juju/unit.py | 16 ++++++++-------- 3 files changed, 33 insertions(+), 19 deletions(-) diff --git a/juju/application.py b/juju/application.py index 74f9057..69f412f 100644 --- a/juju/application.py +++ b/juju/application.py @@ -41,14 +41,14 @@ class Application(model.ModelEntity): """Get the application status, as set by the charm's leader. """ - return self.data['status']['current'] + return self.safe_data['status']['current'] @property def status_message(self): """Get the application status message, as set by the charm's leader. """ - return self.data['status']['message'] + return self.safe_data['status']['message'] @property def tag(self): diff --git a/juju/model.py b/juju/model.py index 621ae06..7897d42 100644 --- a/juju/model.py +++ b/juju/model.py @@ -207,18 +207,16 @@ class ModelEntity(object): self.connected = connected self.connection = model.connection + def __repr__(self): + return '<{} entity_id="{}">'.format(type(self).__name__, + self.entity_id) + def __getattr__(self, name): """Fetch object attributes from the underlying data dict held in the model. """ - if self.data is None: - raise DeadEntityException( - "Entity {}:{} is dead - its attributes can no longer be " - "accessed. Use the .previous() method on this object to get " - "a copy of the object at its previous state.".format( - self.entity_type, self.entity_id)) - return self.data[name] + return self.safe_data[name] def __bool__(self): return bool(self.data) @@ -285,6 +283,22 @@ class ModelEntity(object): return self.model.state.entity_data( self.entity_type, self.entity_id, self._history_index) + @property + def safe_data(self): + """The data dictionary for this entity. + + If this `ModelEntity` points to the dead state, it will + raise `DeadEntityException`. + + """ + if self.data is None: + raise DeadEntityException( + "Entity {}:{} is dead - its attributes can no longer be " + "accessed. Use the .previous() method on this object to get " + "a copy of the object at its previous state.".format( + self.entity_type, self.entity_id)) + return self.data + def previous(self): """Return a copy of this object as was at its previous state in history. @@ -425,13 +439,13 @@ class Model(object): lambda: len(self.machines) == 0 ) - async def block_until(self, *conditions, timeout=None): + async def block_until(self, *conditions, timeout=None, wait_period=0.5): """Return only after all conditions are true. """ async def _block(): while not all(c() for c in conditions): - await asyncio.sleep(0) + await asyncio.sleep(wait_period) await asyncio.wait_for(_block(), timeout) @property diff --git a/juju/unit.py b/juju/unit.py index dc5fa63..ab9d1d0 100644 --- a/juju/unit.py +++ b/juju/unit.py @@ -14,42 +14,42 @@ class Unit(model.ModelEntity): """Returns the current agent status string. """ - return self.data['agent-status']['current'] + return self.safe_data['agent-status']['current'] @property def agent_status_since(self): """Get the time when the `agent_status` was last updated. """ - return parse_date(self.data['agent-status']['since']) + return parse_date(self.safe_data['agent-status']['since']) @property def agent_status_message(self): """Get the agent status message. """ - return self.data['agent-status']['message'] + return self.safe_data['agent-status']['message'] @property def workload_status(self): """Returns the current workload status string. """ - return self.data['workload-status']['current'] + return self.safe_data['workload-status']['current'] @property def workload_status_since(self): """Get the time when the `workload_status` was last updated. """ - return parse_date(self.data['workload-status']['since']) + return parse_date(self.safe_data['workload-status']['since']) @property def workload_status_message(self): """Get the workload status message. """ - return self.data['workload-status']['message'] + return self.safe_data['workload-status']['message'] @property def tag(self): @@ -237,8 +237,8 @@ class Unit(model.ModelEntity): if not status.applications[app]['units'].get(self.name): return False - return status.applications[app]['units'][self.name].get('leader', False) - + return status.applications[app]['units'][self.name].get('leader', + False) async def get_metrics(self): metrics = await self.model.get_metrics(self.tag) -- 2.25.1