コード例 #1
0
ファイル: test_db.py プロジェクト: dgw/sopel
def test_get_nick_id_migration(db: SopelDB):
    """Test nicks with wrong casemapping are properly migrated."""
    nick = 'Test[User]'
    old_nick = Identifier._lower_swapped(nick)

    # sanity check
    assert Identifier(nick).lower() != old_nick, (
        'Previous casemapping should be different from the new one')

    # insert old version
    with db.session() as session:
        nickname = Nicknames(
            nick_id=42,
            slug=Identifier._lower_swapped(nick),
            canonical=nick,
        )
        session.add(nickname)
        session.commit()

    assert db.get_nick_id(nick) == 42, 'Old nick must be converted.'

    with db.session() as session:
        nicknames = session.execute(select(Nicknames)).scalars().fetchall()
        assert len(nicknames) == 1, (
            'There should be only one instance of Nicknames.')
        nickname_found = nicknames[0]
        assert nickname_found.nick_id == 42
        assert nickname_found.slug == Identifier(nick).lower()
        assert nickname_found.canonical == nick
コード例 #2
0
ファイル: db.py プロジェクト: MirahezeBots/sopel
    def get_nick_id(self, nick, create=True):
        """Return the internal identifier for a given nick.

        :param nick: the nickname for which to fetch an ID
        :type nick: :class:`~sopel.tools.Identifier`
        :param bool create: whether to create an ID if one does not exist
        :raise ValueError: if no ID exists for the given ``nick`` and ``create``
                           is set to ``False``
        :raise ~sqlalchemy.exc.SQLAlchemyError: if there is a database error

        The nick ID is shared across all of a user's aliases, assuming their
        nicks have been grouped together.

        .. seealso::

            Alias/group management functions: :meth:`alias_nick`,
            :meth:`unalias_nick`, :meth:`merge_nick_groups`, and
            :meth:`delete_nick_group`.

        """
        session = self.ssession()
        slug = nick.lower()
        try:
            nickname = session.query(Nicknames) \
                .filter(Nicknames.slug == slug) \
                .one_or_none()

            if nickname is None:
                # see if it needs case-mapping migration
                nickname = session.query(Nicknames) \
                    .filter(Nicknames.slug == Identifier._lower_swapped(nick)) \
                    .one_or_none()
                if nickname is not None:
                    # it does!
                    nickname.slug = slug
                    session.commit()

            if nickname is None:  # "is /* still */ None", if Python had inline comments
                if not create:
                    raise ValueError('No ID exists for the given nick')
                # Generate a new ID
                nick_id = NickIDs()
                session.add(nick_id)
                session.commit()

                # Create a new Nickname
                nickname = Nicknames(nick_id=nick_id.nick_id,
                                     slug=slug,
                                     canonical=nick)
                session.add(nickname)
                session.commit()
            return nickname.nick_id
        except SQLAlchemyError:
            session.rollback()
            raise
        finally:
            self.ssession.remove()
コード例 #3
0
ファイル: db.py プロジェクト: MirahezeBots/sopel
    def get_channel_slug(self, chan):
        """Return the case-normalized representation of ``channel``.

        :param str channel: the channel name to normalize, with prefix
                            (required)
        :return str: the case-normalized channel name (or "slug"
                     representation)

        This is useful to make sure that a channel name is stored consistently
        in both the bot's own database and third-party plugins'
        databases/files, without regard for variation in case between
        different clients and/or servers on the network.
        """
        chan = Identifier(chan)
        slug = chan.lower()
        session = self.ssession()
        try:
            count = session.query(ChannelValues) \
                .filter(ChannelValues.channel == slug) \
                .count()

            if count == 0:
                # see if it needs case-mapping migration
                old_rows = session.query(ChannelValues) \
                    .filter(ChannelValues.channel == Identifier._lower_swapped(chan))
                old_count = old_rows.count()
                if old_count > 0:
                    # it does!
                    old_rows.update({ChannelValues.channel: slug})
                    session.commit()

            return slug
        except SQLAlchemyError:
            session.rollback()
            raise
        finally:
            self.ssession.remove()
コード例 #4
0
ファイル: test_db.py プロジェクト: dgw/sopel
def test_get_channel_slug_with_migration(db: SopelDB):
    channel = db.make_identifier('#[channel]')
    db.set_channel_value(channel, 'testkey', 'cval')
    assert db.get_channel_slug(channel) == channel.lower()
    assert db.get_channel_value(channel, 'testkey') == 'cval'

    # insert a value with the wrong casemapping
    old_channel = Identifier._lower_swapped('#[channel]')
    assert old_channel == '#[channel]'
    assert channel.lower() == '#{channel}'

    with db.session() as session:
        channel_value = ChannelValues(
            channel=old_channel,
            key='oldkey',
            value='"value"'  # result from json.dumps
        )
        session.add(channel_value)
        session.commit()

    assert db.get_channel_slug(old_channel) == channel.lower(), (
        'Channel with previous casemapping must return the new version.')
    assert db.get_channel_value(old_channel, 'oldkey') == 'value', (
        'Key associated to an old version must be migrated to the new one')