From 04ccf94d1a836fdb8243dd01b26b9f746abcfeac Mon Sep 17 00:00:00 2001 From: Joey Hines Date: Sun, 29 Jul 2018 08:59:11 -0500 Subject: [PATCH] addtunnel now can't update locations with existing tunnels. Also several other fixes --- BotErrors.py | 5 +++++ Commands.py | 4 ++++ DatabaseInterface.py | 12 ++++++++---- DatabaseModels.py | 16 +++++++++------- Geoffrey.py | 12 +++++++----- test_commands.py | 8 +++++--- test_geoffreyDatabase.py | 34 ++++++++++++++++++++++------------ 7 files changed, 60 insertions(+), 31 deletions(-) diff --git a/BotErrors.py b/BotErrors.py index 82ca764..3d703ee 100644 --- a/BotErrors.py +++ b/BotErrors.py @@ -8,6 +8,8 @@ class LocationInitError(DataBaseError): class TunnelInitError(DataBaseError): '''Error in initializing Tunnel''' +class NoMatchFoundError(DataBaseError): + '''No matches were found in the database''' class LocationLookUpError(DataBaseError): '''Error in finding location in database''' @@ -42,4 +44,7 @@ class InvalidTunnelError(DataBaseError): class PlayerInDB(DataBaseError): """Player already registered in database""" +class LocationHasTunnelError(DataBaseError): + """That location already has a tunnel""" + diff --git a/Commands.py b/Commands.py index ef2773f..97e4eec 100644 --- a/Commands.py +++ b/Commands.py @@ -27,6 +27,7 @@ class Commands: except PlayerNotFound: player = self.interface.add_player(session, player_name, discord_uuid) player_name = player.name + finally: session.close() @@ -140,6 +141,9 @@ class Commands: try: shop_list = self.interface.find_shop_selling_item(session, item_name) + + if len(shop_list) == 0: + raise ItemNotFound finally: session.close() diff --git a/DatabaseInterface.py b/DatabaseInterface.py index 205c40b..7b2e600 100644 --- a/DatabaseInterface.py +++ b/DatabaseInterface.py @@ -17,20 +17,25 @@ class DatabaseInterface: return shop def add_tunnel(self, session, owner, color, number, location_name): + tunnels = self.find_tunnel_by_owner(session, owner) if location_name is None: - if len(self.find_tunnel_by_owner(session, owner)): + if len(tunnels): raise EntryNameNotUniqueError else: location = None else: try: location = self.find_location_by_name_and_owner(session, owner, location_name)[0] + + if location.tunnel is not None: + raise LocationHasTunnelError + except IndexError: raise LocationLookUpError tunnel = Tunnel(owner, color, number, location) - self.database.add_object(session, tunnel) + return tunnel def add_item(self, session, owner, shop_name, item_name, price, amount): @@ -135,8 +140,7 @@ class DatabaseInterface: try: player = self.database.query_by_filter(session, Player, expr)[0] - player.name = grab_playername(player.mc_uuid) - session.commit() + except IndexError: raise PlayerNotFound return player diff --git a/DatabaseModels.py b/DatabaseModels.py index effab64..758073e 100644 --- a/DatabaseModels.py +++ b/DatabaseModels.py @@ -38,13 +38,15 @@ class GeoffreyDatabase: def add_object(self, session, obj): try: - ret = not session.query(exists().where(type(obj).id == obj.id)) - if not ret: + ret = session.query(exists().where(type(obj).id == obj.id)) + if ret: session.add(obj) session.commit() except IntegrityError: + session.rollback() raise EntryNameNotUniqueError except DataError: + session.rollback() raise DatabaseValueError except: session.rollback() @@ -60,11 +62,10 @@ class GeoffreyDatabase: if entry.first() is not None: entry.delete() - session.commit() else: raise DeleteEntryError - session.close() + session.commit() def print_database(self, session, obj_type): obj_list = session.query(obj_type).all() @@ -123,8 +124,9 @@ class Player(SQL_Base): mc_uuid = Column(String(128)) discord_uuid = Column(String(128)) name = Column(String(128)) + locations = relationship("Location", back_populates="owner", lazy='dynamic', - cascade="save-update, merge, delete, delete-orphan") + cascade="save-update, merge, delete, delete-orphan", single_parent=True) tunnels = relationship("Tunnel", back_populates="owner", lazy='dynamic', cascade="save-update, merge, delete, delete-orphan") @@ -143,7 +145,7 @@ class Tunnel(SQL_Base): owner_id = Column(Integer, ForeignKey('Players.id')) owner = relationship("Player", back_populates="tunnels", cascade="save-update, merge, delete") location_id = Column(Integer, ForeignKey('Locations.id', ondelete='CASCADE')) - location = relationship("Location", back_populates="tunnel",) + location = relationship("Location", back_populates="tunnel", lazy="joined") def __init__(self, owner, tunnel_color, tunnel_number, location=None): try: @@ -165,7 +167,7 @@ class Location(SQL_Base): __tablename__ = 'Locations' id = Column(Integer, primary_key=True) - name = Column(String(128), unique=True, ) + name = Column(String(128), unique=True) x = Column(Integer) z = Column(Integer) diff --git a/Geoffrey.py b/Geoffrey.py index 9c47799..a97f9c9 100644 --- a/Geoffrey.py +++ b/Geoffrey.py @@ -132,7 +132,7 @@ async def addshop(ctx, x_pos: int, z_pos: int, *args): async def addtunnel(ctx, tunnel_color: str, tunnel_number: int, *args): ''' Adds your tunnel to the database. - The location name is optional. If the location has a tunnel, it is updated. + The location name is optional. ?tunnel [Tunnel Color] [Tunnel Number] [Location Name] ''' try: @@ -147,6 +147,8 @@ async def addtunnel(ctx, tunnel_color: str, tunnel_number: int, *args): except LocationLookUpError: await bot.say('{}, you do not have a location called **{}**.'.format( ctx.message.author.mention, args[0])) + except LocationHasTunnelError: + await bot.say('{}, **{}** already has a tunnel.'.format(ctx.message.author.mention, args[0])) except TunnelInitError: await bot.say('{}, invalid tunnel color.'.format(ctx.message.author.mention)) except InvalidTunnelError: @@ -197,10 +199,10 @@ async def delete(ctx, * args): if loc is None: raise commands.UserInputError - bot_commands.delete(name, discord_uuid=ctx.message.author.id) - await bot.say('{}, your location named **{}** has been deleted.'.format(ctx.message.author.mention, name)) + bot_commands.delete(loc, discord_uuid=ctx.message.author.id) + await bot.say('{}, your location named **{}** has been deleted.'.format(ctx.message.author.mention, loc)) except (DeleteEntryError, PlayerNotFound): - await bot.say('{}, you do not have a location named **{}**.'.format(ctx.message.author.mention, name)) + await bot.say('{}, you do not have a location named **{}**.'.format(ctx.message.author.mention, loc)) @bot.command(pass_context=True) @@ -278,7 +280,7 @@ async def selling(ctx, item_name: str): result = bot_commands.selling(item_name) await bot.say('{}, the following shops sell **{}**: \n{}'.format(ctx.message.author.mention, item_name, result)) except ItemNotFound: - await bot.say('{}, bo shops sell {}'.format(ctx.message.author.mention, item_name)) + await bot.say('{}, no shops sell **{}**'.format(ctx.message.author.mention, item_name)) @bot.command(pass_context=True) diff --git a/test_commands.py b/test_commands.py index 0d13316..e95d8fb 100644 --- a/test_commands.py +++ b/test_commands.py @@ -61,8 +61,9 @@ class TestCommands(TestCase): if 'Green' not in tunnel2: self.fail() - else: - pass + + self.assertRaises(LocationHasTunnelError, self.commands.addtunnel, 'Blue', 50, location_name='test_shop', + discord_uuid='143072699567177728') def test_find(self): self.commands.register('ZeroHD', '143072699567177728') @@ -84,7 +85,6 @@ class TestCommands(TestCase): self.assertRaises(LocationLookUpError, self.commands.find, 'zerohd') - def test_findaround(self): self.commands.register('ZeroHD', '143072699567177728') self.commands.addshop(0, 0, shop_str='frick', discord_uuid='143072699567177728') @@ -154,3 +154,5 @@ class TestCommands(TestCase): pass else: self.fail() + + diff --git a/test_geoffreyDatabase.py b/test_geoffreyDatabase.py index 6000f28..bdff309 100644 --- a/test_geoffreyDatabase.py +++ b/test_geoffreyDatabase.py @@ -11,24 +11,28 @@ class TestGeoffreyDatabase(TestCase): engine_arg = config['SQL']['test_args'] self.commands = Commands(engine_arg) + + self.session = self.commands.interface.database.Session() + self.commands.interface.database.clear_all(self.session) self.owner = Player('ZeroHD', '143072699567177728') self.loc = Location('test', 1, 3, self.owner, dimension='Nether') self.tunnel = Tunnel(self.owner, 'Green', 105, self.loc) - self.session = self.commands.interface.database.Session() - self.commands.interface.database.clear_all(self.session) - def tearDown(self): + self.session.commit() self.session.close() def add_shop(self, player): - return self.commands.interface.add_shop(self.session, player, 'test', 1, 3, "nether") + shop = self.commands.interface.add_shop(self.session, player, 'test', 1, 3, "nether") + return shop def add_player(self): - return self.commands.interface.add_player(self.session, 'ZeroHD', discord_uuid='143072699567177728') + player = self.commands.interface.add_player(self.session, 'ZeroHD', discord_uuid='143072699567177728') + return player def add_loc(self, player): - return self.commands.interface.add_location(self.session, player, 'test', 0, 0) + loc = self.commands.interface.add_location(self.session, player, 'test', 0, 0) + return loc def test_add_object(self): self.commands.interface.database.add_object(self.session, self.loc) @@ -54,10 +58,17 @@ class TestGeoffreyDatabase(TestCase): def test_delete_entry(self): self.commands.interface.database.add_object(self.session, self.loc) self.commands.interface.database.add_object(self.session, self.owner) - + self.session.commit() + id = self.loc.owner_id expr = Location.owner == self.owner self.commands.interface.database.delete_entry(self.session, Location, expr) + expr = Player.name == 'ZeroHD' + player = self.commands.interface.database.query_by_filter(self.session, Player, expr)[0] + self.assertEqual(player.name, 'ZeroHD') + + expr = Location.owner == player + loc2 = self.commands.interface.database.query_by_filter(self.session, Location, expr) self.assertEqual(len(loc2), 0) @@ -83,13 +94,14 @@ class TestGeoffreyDatabase(TestCase): self.assertEqual(loc_list[1].id, shop2.id) def test_add_tunnel(self): - self.session = self.commands.interface.database.Session() player = self.add_player() tunnel1 = self.commands.interface.add_tunnel(self.session, player, 'green', 155, None) tunnel2 = self.commands.interface.find_tunnel_by_owner_name(self.session, 'ZeroHD')[0] self.assertEqual(tunnel1, tunnel2) + + def test_add_item(self): owner = self.add_player() self.add_shop(owner) @@ -115,16 +127,14 @@ class TestGeoffreyDatabase(TestCase): self.assertEqual(loc_list[0].id, shop.id) def test_delete_base(self): - self.session = self.commands.interface.database.Session() owner = self.add_player() self.add_loc(owner) self.commands.interface.delete_location(self.session, owner, 'test') - loc_list = self.commands.interface.find_location_by_name_and_owner(self.session, owner, 'test') + loc_list = self.commands.interface.find_location_by_name(self.session, 'test') self.assertEqual(len(loc_list), 0) - self.session.close() def test_find_location_around(self): owner = self.add_player() @@ -195,7 +205,7 @@ class TestGeoffreyDatabase(TestCase): def test_big_input(self): owner = self.add_player() - self.assertRaises(StringTooLong, self.commands.interface.add_location, self.session, owner, + self.assertRaises(DatabaseValueError, self.commands.interface.add_location, self.session, owner, 'TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT' 'TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT' 'TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT', 0, 0,)