Skip to content
Permalink
Browse files

feat(pymock): repl, guarded dict access with defaults

  • Loading branch information
CinchBlue committed Dec 5, 2019
1 parent 2daed1e commit 0a77ec0c320be0f3a4fca688e3bf014b1624f02e
Showing with 95 additions and 19 deletions.
  1. +95 −19 python/mock.py
@@ -11,8 +11,17 @@ def __init__(self, **kwargs):
for key, value in kwargs.items():
self.attr[key] = value

def __str__(self):
return "[{}] {}".format(
def __str__(self) -> str:
place_type = self.attr['primtype'] \
if 'primtype' in self.attr \
else '?'
place_value = '"{}"'.format(self.attr['name']) \
if 'name' in self.attr \
else (self.attr['value'] if 'value' in self.attr else '?')
return '{}: {}'.format(place_type, place_value)

def __repr__(self) -> str:
return "P[{}] {}".format(
self.id,
self.attr)

@@ -35,13 +44,19 @@ def __init__(
self.attr[key] = value

def __str__(self):
return "[{}] {} => {} => {} {}".format(
return "L[{}] ({}) {} => {} => {} {}".format(
self.id,
self.from_place,
self.name,
self.from_place,
self.to_place,
self.attr)

def __repr__(self):
return "({}) {} -> {}".format(
self.name,
self.from_place,
self.to_place)


class GraphStore:
"""Store in which to store places and links"""
@@ -55,7 +70,7 @@ def insert_place(self, place: Place):
self.places[place.id] = place

def get_place(self, place_id: uuid.UUID) -> Place:
return self.places[place_id]
return self.places.get(place_id, None)

def remove_place(self, place_id: uuid.UUID):
if place_id in self.places:
@@ -77,13 +92,13 @@ def insert_link(self, link: Link):
self.links_by_to[link.to_place][link.id] = link

def get_link(self, link_id: uuid.UUID) -> Link:
return self.links[link_id]
return self.links.get(link_id, None)

def get_links_from(self, place_id: uuid.UUID) -> Dict[uuid.UUID, Link]:
return self.links_by_from[place_id]
return self.links_by_from.get(place_id, {})

def get_links_to(self, place_id: uuid.UUID) -> Dict[uuid.UUID, Link]:
return self.links_by_to[place_id]
return self.links_by_to.get(place_id, {})

def remove_link(self, link_id: uuid.UUID):
if link_id in self.links:
@@ -116,7 +131,7 @@ def evaluate(self, root: Place, graph: GraphStore) -> int:
elif root.attr["primtype"] == "Integer":
return root.attr["value"]
else:
raise RuntimeError("What the fuck this wasn't a Proc or Int!")
raise RuntimeError("What the duck this wasn't a Proc or Int!")


class GraphTraversalContext:
@@ -144,8 +159,12 @@ def innl(self) -> Dict[str, Link]:
in_links = self.inl()
return {v.name: v for k, v in in_links.items()}

def focus_attr(self, attr_name: str):
"""Traverse from the current place to another by way of"""
def focus(self, attr_name: str):
"""Focus a connected connected place by attrbiute name"""
self.focus_name(attr_name)

def focus_name(self, attr_name: str):
"""Traverse from the current place to another by way of link name"""
attr_links = self.outnl()
if attr_name in attr_links:
self.place = gs.get_place(attr_links[attr_name].to_place)
@@ -158,22 +177,52 @@ def focus_link(self, id: uuid.UUID):
self.place = gs.get_place(out_links[id].to_place)
self.place_stack.append(self.place.id)

def focus_place(self, id: uuid.UUID):
self.place = self.gs.get_place(id)
self.place_stack.append(self.place.id)

def prev(self):
if self.place_stack:
"""Show the previous place in the place stack"""
if self.place_stack and len(self.place_stack) > 2:
print(gs.get_place(self.place_stack[-2]))
else:
self.curr()

def back(self):
"""If possible, pops the place stack by 1"""
if self.place_stack and len(self.place_stack) > 1:
self.place_stack.pop()
self.place = gs.get_place(self.place_stack[-1])
self.curr()

def curr(self):
"""Prints out a representation of the current place"""
print(self.place)

def eval(self):
"""Evaluates the current expression starting from the current place"""
evaluator = BasicEvaluator()
print(evaluator.evaluate(self.place, self.gs))

def set_attr(self, name: str, item):
self.place.attr[name] = item

def get_attr(self, name: str):
return self.place.attr[name]

def show(self) -> str:
"""Gives a summary of the current place + out links"""
self.curr()
for out_name, out_link in self.outnl().items():
place = self.gs.get_place(out_link.to_place)
if place:
place_str = str(place)
print('|-- {} => {}'.format(out_name, place_str))


gs = GraphStore()

# Create an arithmetic expression
# Create an arithmetic expression going top-down for (+ 0 .. 11)
toplevel_root = Place(primtype="Procedure", name="+")
root = toplevel_root
gs.insert_place(root)
@@ -205,14 +254,41 @@ def eval(self):
right_link = Link(root.id, final_rhs.id, "op2", type="Possession")
gs.insert_link(right_link)

print(BasicEvaluator().evaluate(toplevel_root, gs))
assert BasicEvaluator().evaluate(toplevel_root, gs) == 66

# Now that we have a "graph," let's traverse over it.

# Here, we are setting up the interactive GraphTraversalContext
cxt = GraphTraversalContext(toplevel_root.id, gs)

# Try do:
#
# cxt.outln()
# cxt.focus("op1")
# print(cxt.place)
# We put in some easy commands
commands = {}
commands['c'] = cxt.show
commands['f'] = cxt.focus
commands['b'] = cxt.back
commands['e'] = cxt.eval
commands['i'] = cxt.innl
commands['o'] = cxt.outnl

def command_help():
"""Prints every current bound command and its documentation string"""
for command_name, command in commands.items():
print('{}: {}'.format(command_name, command.__doc__))


commands['?'] = command_help

print('Welcome to Shock! An example expression has already been initialized '
'for you. To exit, press Ctrl+C (Ctrl+Z for Windows) twice.')
while True:
raw_command = input('> ')
command = raw_command.split()
if command[0] in commands:
try:
result = commands[command[0]](*command[1:])
if result:
print(result)
except Exception as err:
print(repr(err))
else:
print('"{}" is not a valid command (see "?")'.format(raw_command))

0 comments on commit 0a77ec0

Please sign in to comment.
You can’t perform that action at this time.