Skip to content

Commit

Permalink
Merge pull request #55 from diggyk/master
Browse files Browse the repository at this point in the history
Refactored Labors and Fates
  • Loading branch information
leojli committed Sep 29, 2015
2 parents 696ce09 + 5de3c4f commit 00d54ff
Show file tree
Hide file tree
Showing 11 changed files with 263 additions and 19 deletions.
19 changes: 17 additions & 2 deletions hermes/handlers/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -1185,6 +1185,7 @@ def post(self):
"completionEventTypeId": 2,
"description": "This is a fate",
"follows_id": 1,
"for_creator": true,
}
**Example response:**
Expand All @@ -1201,6 +1202,7 @@ def post(self):
"creationEventTypeId": 1,
"completionEventTypeId": 2,
"follows": 1,
"for_creator": true,
"description": "This is a fate"
}
Expand All @@ -1224,6 +1226,8 @@ def post(self):
creation_event_type_id = self.jbody["creationEventTypeId"]
completion_event_type_id = self.jbody["completionEventTypeId"]
follows_id = self.jbody.get("follows_id")
for_creator = self.jbody.get("for_creator", False)
for_owner = self.jbody.get("for_owner", True)
description = self.jbody["description"]
except KeyError as err:
raise exc.BadRequest(
Expand Down Expand Up @@ -1251,7 +1255,9 @@ def post(self):
try:
fate = Fate.create(
self.session, creation_event_type, completion_event_type,
follows_id=follows_id, description=description
follows_id=follows_id, for_creator=for_creator,
for_owner=for_owner,
description=description
)
except IntegrityError as err:
raise exc.Conflict(err.orig.message)
Expand Down Expand Up @@ -1293,6 +1299,7 @@ def get(self):
"creationEventTypeId": 1,
"completionEventType": 2,
"follows_id": null,
"for_creator": 0,
"precedes_ids": [3, 5],
"description": "This is a fate",
},
Expand Down Expand Up @@ -1352,7 +1359,9 @@ def get(self, id):
"href": "/api/v1/fates/1",
"creationEventTypeId": 1,
"completionEventType": 2,
"intermediate": true|false,
"follows_id": null,
"for_creator": false,
"for_owner": true,
"description": string,
}
Expand Down Expand Up @@ -1404,6 +1413,8 @@ def put(self, id):
"creationEventTypeId": 1,
"completionEventType": 2,
"follows_id": 1,
"for_creator": false,
"for_owner": true
"description": "New desc"
}
Expand Down Expand Up @@ -1484,6 +1495,8 @@ def get(self):
"id": 23,
"startingLaborId": null,
"href": "/api/v1/labors/23",
"for_owner": false,
"for_creator": true,
"questId": 5,
"hostId": 26,
"creationTime": timestamp,
Expand Down Expand Up @@ -1656,6 +1669,8 @@ def get(self, id):
"startingLaborId": null,
"questId": 5,
"hostId": 26,
"for_creator": true,
"for_owner": false,
"creationTime": timestamp,
"targetTime": timestamp,
"ackTime": timestamp,
Expand Down
79 changes: 74 additions & 5 deletions hermes/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -508,10 +508,15 @@ class Fate(Model):
follows: indicates that this Fate only comes into affect if fulfilling
the Fate with this specified id
precedes: indicates which Fates are chained to come after this Fate
for_creator: if true, the labor created will be designated for the quest creator
for_owner: if true, the labor creator will be designated for the server owner
description: the optional human readable description of this Fate
_all_fates: cached list of all Fates
_intermediate_fates = cached list of all intermediate Fates (Fates that follow other Fates)
_starting_fates = cached list of all non-intermediate Fates
Notes:
A Fate can create a Labor can be designated for both the server owner and the quest owner
"""

__tablename__ = "fates"
Expand Down Expand Up @@ -544,6 +549,9 @@ class Fate(Model):
"Fate", lazy="joined", backref="precedes", remote_side=[id]
)

for_creator = Column(Boolean, nullable=False, default=False)
for_owner = Column(Boolean, nullable=False, default=True)

description = Column(String(2048), nullable=True)
__table_args__ = (
UniqueConstraint(
Expand All @@ -563,7 +571,7 @@ class Fate(Model):
def create(
cls, session,
creation_event_type, completion_event_type, follows_id=None,
description=None
for_creator=False, for_owner=True, description=None
):
"""Create a Fate
Expand All @@ -573,6 +581,8 @@ def create(
completion_event_type: an EventType that will trigger
an labor completion
follows_id: id of the Fate this new Fate will follow; None if non-intermediate
for_creator: if true, Fate will create labors for the quest creator
for_owner: if true, Fate will create labors for the server owner
description: optional description for display
Returns:
Expand All @@ -596,11 +606,19 @@ def create(
"EventType for the preceding Fate do not match"
)

if not for_creator and not for_owner:
raise exc.ValidationError(
"Fate must designate labors for the machine owner, "
"quest creator, or both."
)

try:
obj = cls(
creation_event_type=creation_event_type,
completion_event_type=completion_event_type,
follows_id=follows_id,
for_creator=for_creator,
for_owner=for_owner,
description=description
)
obj.add(session)
Expand Down Expand Up @@ -635,7 +653,9 @@ def _refresh_cache(cls, session):
"follows_id": fate.follows_id,
"precedes_ids": [
linked_fate.id for linked_fate in fate.precedes
]
],
"for_creator": fate.for_creator,
"for_owner": fate.for_owner
}
Fate._all_fates.append(fate_dict)
if fate.follows_id:
Expand Down Expand Up @@ -748,7 +768,9 @@ def question_the_fates(cls, session, events, quest=None):
new_labor_dict = {
"host_id": host.id,
"creation_event_id": event.id,
"quest_id": quest.id if quest else None
"quest_id": quest.id if quest else None,
"for_creator": fate["for_creator"],
"for_owner": fate["for_owner"]
}
if new_labor_dict not in all_new_labors:
all_new_labors.append(new_labor_dict)
Expand Down Expand Up @@ -781,8 +803,15 @@ def question_the_fates(cls, session, events, quest=None):
# Since this Fate closes this Labor, let's see
# if this Fate also precedes other Fates. If so,
# we can make the assumption that a new Labor
# should be created
# should be created. We will examine those
# subsequent labors to see if the labor should be
# for the quest creator, server owner, or both.
if fate["precedes_ids"]:
designations = Fate.get_designations(
all_fates,
fate['precedes_ids']
)

new_labor_dict = {
"host_id": host.id,
"starting_labor_id": (
Expand All @@ -793,7 +822,9 @@ def question_the_fates(cls, session, events, quest=None):
"creation_event_id": event.id,
"quest_id": (
labor.quest.id if labor.quest else None
)
),
"for_creator": designations["for_creator"],
"for_owner": designations["for_owner"],
}
if new_labor_dict not in all_new_labors:
all_new_labors.append(new_labor_dict)
Expand All @@ -806,6 +837,21 @@ def question_the_fates(cls, session, events, quest=None):
session.flush()
session.commit()

@classmethod
def get_designations(cls, fates, ids):
for_owner = False
for_creator = False

for fate in fates:
if fate["id"] in ids:
for_owner = for_owner or fate["for_owner"]
for_creator = for_creator or fate["for_creator"]

return {
"for_owner": for_owner,
"for_creator": for_creator
}

def href(self, base_uri):
"""Create an HREF value for this object
Expand Down Expand Up @@ -839,6 +885,8 @@ def to_dict(self, base_uri=None, expand=None):
"completionEventTypeId": self.completion_type_id,
"follows_id": self.follows_id,
"precedes_ids": [labor.id for labor in self.precedes],
"for_creator": self.for_creator,
"for_owner": self.for_owner,
"description": self.description,
}

Expand Down Expand Up @@ -1356,6 +1404,8 @@ class Labor(Model):
starting_labor_id: the database id of the labor that started chain of intermediate labors
quest: the Quest to this this Labor belongs
host: the Host to which this Labor pertains
for_creator: if true, the labor will be designated for the quest creator
for_labor: if true, the labor is designate for the server owner
creation_time: when this Labor was created
ack_time: when this Labor was acknowledged
ack_user: the user who acknowledged the Labor
Expand All @@ -1366,38 +1416,55 @@ class Labor(Model):
Notes:
the user field is for auditing purposes only. It is not enforced or
validated in any way.
A Labor can be designated for both the server owner and the Quest owner
"""

__tablename__ = "labors"

id = Column(Integer, primary_key=True)

starting_labor_id = Column(Integer, nullable=True, index=True)

quest_id = Column(
Integer, ForeignKey("quests.id"), nullable=True, index=True
)

quest = relationship(Quest, lazy="joined", backref="labors")

host_id = Column(
Integer, ForeignKey("hosts.id"), nullable=False, index=True
)

host = relationship(
Host, lazy="joined", backref="labors"
)

for_creator = Column(Boolean, nullable=False, default=False)
for_owner = Column(Boolean, nullable=False, default=True)

creation_time = Column(
DateTime, default=datetime.utcnow, nullable=False, index=True
)

ack_time = Column(DateTime, nullable=True)

ack_user = Column(String(64), nullable=True)

completion_time = Column(DateTime, nullable=True)

creation_event_id = Column(
Integer, ForeignKey("events.id"), nullable=False, index=True
)

creation_event = relationship(
Event, lazy="joined", backref="created_labors",
foreign_keys=[creation_event_id]
)

completion_event_id = Column(
Integer, ForeignKey("events.id"), nullable=True, index=True
)

completion_event = relationship(
Event, lazy="joined", backref="completed_labors",
foreign_keys=[completion_event_id]
Expand Down Expand Up @@ -1568,6 +1635,8 @@ def to_dict(self, base_uri=None, expand=None):
"startingLaborId": self.starting_labor_id,
"questId": self.quest_id,
"hostId": self.host_id,
"for_creator": self.for_creator,
"for_owner": self.for_owner,
"creationTime": str(self.creation_time),
"creationEventId": self.creation_event_id,
"completionTime": (
Expand Down
2 changes: 2 additions & 0 deletions tests/api_tests/data/set1/fates.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
"creationEventTypeId": 4,
"completionEventTypeId": 5,
"follows_id": 2,
"for_creator": true,
"for_owner": false,
"description": "Maintenance must be performed on a system that is prepped."
}
}
31 changes: 31 additions & 0 deletions tests/api_tests/test_fates.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,25 @@ def test_malformed(sample_data1_server):
assert_error(client.post("/fates", data="Non-JSON"), 400)


def test_bad_creation(sample_data1_server):
"""Fate's must be either set to for_owner, for_creator, or both"""
client = sample_data1_server
assert_error(
client.post(
"/fates",
data={
"creationEventTypeId": 6,
"completionEventTypeId": 7,
"for_owner": False,
"for_creator": False,
"precedes_ids": [],
"description":"New fate"
}
),
400
)


def test_creation(sample_data1_server):
client = sample_data1_server
assert_success(
Expand Down Expand Up @@ -43,6 +62,8 @@ def test_creation(sample_data1_server):
"creationEventTypeId": 6,
"completionEventTypeId": 7,
"follows_id": None,
"for_owner": True,
"for_creator": False,
"precedes_ids": [],
"description": "New fate"
}
Expand All @@ -68,6 +89,8 @@ def test_update(sample_data1_server):
"creationEventTypeId": 6,
"completionEventTypeId": 7,
"follows_id": None,
"for_owner": True,
"for_creator": False,
"precedes_ids": [],
"description": "New fate"
}
Expand All @@ -83,6 +106,8 @@ def test_update(sample_data1_server):
"creationEventTypeId": 6,
"completionEventTypeId": 7,
"follows_id": 1,
"for_owner": True,
"for_creator": False,
"precedes_ids": [],
"description": "New fate"
}
Expand All @@ -98,6 +123,8 @@ def test_update(sample_data1_server):
"creationEventTypeId": 6,
"completionEventTypeId": 7,
"follows_id": 1,
"for_owner": True,
"for_creator": False,
"precedes_ids": [],
"description": "New desc"
}
Expand All @@ -114,6 +141,8 @@ def test_update(sample_data1_server):
"creationEventTypeId": 6,
"completionEventTypeId": 7,
"follows_id": None,
"for_owner": True,
"for_creator": False,
"precedes_ids": [],
"description": "Another desc"
}
Expand All @@ -126,6 +155,8 @@ def test_update(sample_data1_server):
"creationEventTypeId": 6,
"completionEventTypeId": 7,
"follows_id": None,
"for_owner": True,
"for_creator": False,
"precedes_ids": [],
"description": "Another desc"
}
Expand Down

0 comments on commit 00d54ff

Please sign in to comment.