class StorageTest(unittest.TestCase): @patch('wasabi2d.storage.os.path.exists') def setUp(self, exists_mock): exists_mock.return_value = True self.storage = Storage('asdf') @patch('builtins.open', mock.mock_open(read_data='{"a": "hello"}')) def test_get(self): self.storage.load() self.assertEqual(self.storage['a'], 'hello')
def test_invalid_list_item(self): """We can report the index of an unserialisable list item.""" obj = {'items': [1, 5, threading.Lock()]} result = sorted(Storage._get_json_error_keys(obj)) self.assertEqual(result, [ ("storage['items'][2]", '_thread.lock'), ])
def test_dict_with_nested_dicts_errors(self): subobj0 = {'this_key_fails': object()} subobj1 = {'a': 10, 'b': {1, 2, 3}, 'c': 30, 'obj': subobj0} subobj2 = {'player_name': 'Daniel', 'level': 20, 'states': subobj1} obj = {'game': 'my_game', 'state': subobj2} result = sorted(Storage._get_json_error_keys(obj)) self.assertEqual(result, [ ("storage['state']['states']['b']", 'set'), ("storage['state']['states']['obj']['this_key_fails']", 'object'), ])
def __init__(self): self.scene = Scene(title='Cast Away!', icon='logo', width=800, height=600) self.scene.background = 0.9, 0.9, 1.0 self.activity = None self.fade_layer = self.scene.layers[30] self.info_layer1 = self.scene.layers[31] self.info_layer2 = self.scene.layers[32] self.missile_mask = self.scene.layers[40] self.action_layers = chain.LayerRange(stop=5) self.fade_layers = chain.Layers([30]) self.info_layers = chain.Layers([31, 32]) self.island_layers = [ chain.Layers([6]), chain.Mask( paint=chain.Fill((0, 0, .2, .5)), mask=chain.Layers([7]), function='inside', ), chain.LayerRange(start=8, stop=11), ] self.info_node = InfoNode(self.info_layers) self.input_locked = False self.island = None self.info = Info(self, self.info_layer1, self.info_layer2) self.island = Island(self) self.scene.chain = [ self.action_layers, self.info_node, ] self.info_layer1.set_effect('dropshadow', radius=3, offset=(0, 0), opacity=3) self.fade_circ = self.fade_layer.add_sprite( 'blur_circle', scale=hypot(self.scene.width, self.scene.height) // 2 / 50, pos=(self.scene.width // 2, self.scene.height * 0.55), ) self.fade_rect = self.fade_layer.add_rect( self.scene.width * 3, self.scene.height * 3, color=(0, 0, 0, 0), ) self.storage = Storage('mufl_castaway.json') self.storage.load() self.info.load(self.storage) if self.info.food > 0: self.return_to_island() set_music('main') else: self.go_do(None, from_island=False) set_music('intro')
class Game: def __init__(self): self.scene = Scene(title='Cast Away!', icon='logo', width=800, height=600) self.scene.background = 0.9, 0.9, 1.0 self.activity = None self.fade_layer = self.scene.layers[30] self.info_layer1 = self.scene.layers[31] self.info_layer2 = self.scene.layers[32] self.missile_mask = self.scene.layers[40] self.action_layers = chain.LayerRange(stop=5) self.fade_layers = chain.Layers([30]) self.info_layers = chain.Layers([31, 32]) self.island_layers = [ chain.Layers([6]), chain.Mask( paint=chain.Fill((0, 0, .2, .5)), mask=chain.Layers([7]), function='inside', ), chain.LayerRange(start=8, stop=11), ] self.info_node = InfoNode(self.info_layers) self.input_locked = False self.island = None self.info = Info(self, self.info_layer1, self.info_layer2) self.island = Island(self) self.scene.chain = [ self.action_layers, self.info_node, ] self.info_layer1.set_effect('dropshadow', radius=3, offset=(0, 0), opacity=3) self.fade_circ = self.fade_layer.add_sprite( 'blur_circle', scale=hypot(self.scene.width, self.scene.height) // 2 / 50, pos=(self.scene.width // 2, self.scene.height * 0.55), ) self.fade_rect = self.fade_layer.add_rect( self.scene.width * 3, self.scene.height * 3, color=(0, 0, 0, 0), ) self.storage = Storage('mufl_castaway.json') self.storage.load() self.info.load(self.storage) if self.info.food > 0: self.return_to_island() set_music('main') else: self.go_do(None, from_island=False) set_music('intro') def set_missile_chain(self): fill = chain.Fill((0, 0, 0, 1)) self.scene.chain = [ chain.Fill((0.835, 0.964, 1, 1)), chain.Layers([6]), chain.Mask( paint=chain.Fill((0, 0, .2, .5)), mask=chain.Layers([7]), function='inside', ), chain.Mask( paint=[chain.LayerRange(start=8, stop=11), self.info_node], mask=fill, ), chain.Layers([1, 2]), ] return fill def set_molten_chain(self): self.scene.layers.pop(40, None) self.scene.chain = [ self.action_layers, chain.Mask( paint=[chain.Fill((0.607, 0.592, 0.235)), chain.Layers([40])], mask=chain.Layers([1]), ), self.info_node, ] return self.scene.layers[40] def go_do(self, idx, from_island=True): if idx == 4 and self.info.message_assembled: set_music('win') self.island.fire_missile() return if idx is not None: self.info.food -= 1 play_sound('menu-select') self.activity = None for i in range(5): self.scene.layers.pop(i, None) async def coro(): self.input_locked = True try: if from_island: self.scene.chain = [ *self.island_layers, self.fade_layers, self.info_node, ] self.fade_circ.color = (0, 0, 0, 0) self.fade_rect.color = (0, 0, 0, 0) await animate(self.fade_rect, color=(0, 0, 0, 1), duration=0.25, tween='accelerate') black = clock.coro.sleep(0.25) if idx == None: self.go_intro() elif idx == 0: self.go_fish() elif idx == 1: self.go_dice() elif idx == 2: if self.info.things_full: self.go_castaway() else: self.go_burrow() elif idx == 3: self.go_shadow() elif idx == 4: self.go_ask() else: await black print('ERROR, unknown action') self.return_to_island() return self.scene.chain = [ self.action_layers, self.fade_layers, self.info_node, ] set_music(getattr(self.activity, 'music_track', None)) await black await animate(self.fade_rect, color=(0, 0, 0, 0), duration=0.25, tween='accelerate') self.fade_rect.color = (0, 0, 0, 0) self.scene.chain = [ self.action_layers, self.info_node, ] finally: self.input_locked = False clock.coro.run(coro()) def go_fish(self): self.activity = Fishing( self, on_finish=self.finish_activity, ) def go_dice(self): self.activity = DiceThrowing( self, on_finish=self.finish_activity, ) def go_burrow(self): self.activity = Burrowing(self) def go_shadow(self): self.activity = Shadowing(self) def go_ask(self): self.activity = AskMissile(self) def go_castaway(self): self.activity = CastAway(self) def go_intro(self): self.activity = Intro(self) def save(self): self.info.save(self.storage) # TODO: report bug! -- self.storage._ensure_save_path() storage_path = self.storage.STORAGE_DIR try: os.makedirs(storage_path) except (FileExistsError, IsADirectoryError): pass self.storage.save() def return_to_island(self): if self.activity: self.activity.active = False self.save() self.scene.layers.pop(40, None) self.activity = self.island self.scene.chain = [ *self.island_layers, self.info_node, ] self.island.reset() def finish_activity(self, speedup=1, superfast=False, extra_delay=4, **bonus): old_activity = self.activity self.activity = None set_music('main') self.save() async def coro(): self.input_locked = True try: if speedup == 1: tween = 'accelerate' efs = getattr(self.activity, 'end_fadeout_scale', 100 / 64) else: tween = 'linear' efs = 0 self.fade_circ.color = (0, 0, 0, 1) self.fade_circ.scale = hypot(self.scene.width, self.scene.height) // 2 / 50 ani = animate(self.fade_circ, scale=efs, duration=5 / speedup, tween=tween) self.scene.chain = [ chain.Fill(color=(.1, .1, .1, 1)), chain.Mask( mask=self.fade_layers, paint=[ chain.Fill(color=self.scene.background), self.action_layers ], ), self.info_node, ] if extra_delay: await clock.coro.sleep(extra_delay) self.info.give(sleep=1, **bonus) await ani if old_activity: old_activity.active = False if self.fade_circ.scale: await clock.coro.sleep(1) await animate(self.fade_circ, scale=0, duration=self.fade_circ.scale, tween='accelerate') self.scene.chain = [ *self.island_layers, self.fade_layers, self.info_node, ] self.fade_rect.color = (0, 0, 0, 1) await animate(self.fade_rect, color=(0, 0, 0, 0), duration=0.25, tween='accelerate') for i in range(5): self.scene.layers.pop(i, None) finally: self.input_locked = False self.return_to_island() clock.coro.run(coro()) def abort_activity(self, return_food=True, deselect=False, on_done=None): if return_food: self.info.food += 1 self.activity = None set_music('main') self.save() async def coro(): self.input_locked = True try: self.scene.chain = [ self.action_layers, self.fade_layers, self.info_node, ] self.fade_circ.color = (0, 0, 0, 0) self.fade_rect.color = (0, 0, 0, 0) await animate(self.fade_rect, color=(0, 0, 0, 1), duration=0.25, tween='accelerate') black = clock.coro.sleep(0.25) for i in range(5): self.scene.layers.pop(i, None) self.scene.chain = [ *self.island_layers, self.fade_layers, self.info_node, ] self.activity = self.island self.island.reset() await black await animate(self.fade_rect, color=(0, 0, 0, 0), duration=0.25, tween='accelerate') self.scene.chain = [ *self.island_layers, self.info_node, ] finally: self.input_locked = False if on_done: on_done() clock.coro.run(coro()) if deselect: self.island.deselect() def on_key_down(self, key): if self.input_locked: return try: on_key_down = self.activity.on_key_down except AttributeError: pass else: return on_key_down(key) def on_key_up(self, key): if self.input_locked: return try: on_key_up = self.activity.on_key_up except AttributeError: pass else: return on_key_up(key)
def test_dict_with_no_errors(self): obj = {'level': 10, 'player_name': 'Daniel'} result = list(Storage._get_json_error_keys(obj)) self.assertEqual(result, [])
def setUp(self, exists_mock): exists_mock.return_value = True self.storage = Storage('asdf')
def test_dict_with_errors(self): obj = {'level': 10, 'player_name': 'Daniel', 'obj': object()} result = list(Storage._get_json_error_keys(obj)) self.assertEqual(result, [("storage['obj']", "object")])