pythonpython-3.xormponyorm

How can i drop table after finish my scenario?


i have a problem with drop table after finish my scenario when I try to delete using db.drop_table(Routes, if_exists=False, with_all_data=False) or db.drop_table(Routes, if_exists=True, with_all_data=True) i get an error pony.orm.core.TransactionError: @db_session-decorated drop_table() function with ddl option cannot be called inside of another db_sessio i try to delete using Routes.delete() and I got the same one i read more documentation and i dont know how can i drop this table

my full code

import logging
import random

import requests
import vk_api
from pony.orm import db_session, rollback
from vk_api.bot_longpoll import VkBotLongPoll, VkBotEventType

import handlers
from models import UserState, Registration, Routes, db

try:
    import settings
except ImportError:
    exit('DO CP settings.py.default setting.py and set token')

log = logging.getLogger('bot')


def configure_logging():
    stream_handler = logging.StreamHandler()
    stream_handler.setFormatter(logging.Formatter('%(levelname)s %(message)s'))
    stream_handler.setLevel(logging.INFO)
    log.addHandler(stream_handler)
    file_handler = logging.FileHandler('bot.log')
    file_handler.setFormatter(logging.Formatter('%(asctime)s %(levelname)s %(message)s'))
    file_handler.setLevel(logging.DEBUG)
    log.addHandler(file_handler)


class Bot:
    """
    Echo bot for vk.com
    Use python 3.7
    """

    def __init__(self, group_id, token):
        """
        :param group_id:group_id from group vk.com
        :param token:secret key
        """
        self.group_id = group_id
        self.token = token
        self.vk = vk_api.VkApi(token=self.token)
        self.long_poller = VkBotLongPoll(self.vk, self.group_id)
        self.api = self.vk.get_api()

    def run(self):

        """run bot"""

        for event in self.long_poller.listen():
            try:
                print(event)
                self.on_event(event)
            except Exception:
                log.exception('ошибка в обработке события')

    @db_session
    def on_event(self, event):
        """
        sends the message back, if message text
        :param event: VKBotMessageEvent object
        :return: None
        """
        if event.type != VkBotEventType.MESSAGE_NEW:
            log.info('пока не умеем работать с таким типом события %s', event.type)
            return
        user_id = event.message.peer_id
        text = event.message.text
        state = UserState.get(user_id=str(user_id))
        if state is not None:
            self.continue_scenario(text=text, state=state, user_id=user_id)
        else:
            # search intent, the user is found outside of the scenario
            for intent in settings.INTENTS:
                log.debug(f'User gets {intent}')
                if any(token in text.lower() for token in intent['tokens']):
                    # run intent
                    if intent['answer']:
                        self.send_text(text_to_send=intent['answer'], user_id=user_id)
                    else:
                        self.start_scenario(scenario_name=intent['scenario'], user_id=user_id, text=text)
                    break
            else:
                self.send_text(text_to_send=settings.DEFAULT_ANSWER, user_id=user_id)

    # функция отправки текста
    def send_text(self, text_to_send, user_id):
        self.api.messages.send(
            message=text_to_send,
            random_id=random.randint(0, 2 ** 20),
            peer_id=user_id)

    # функция отправки изображения
    def send_image(self, image, user_id):
        upload_url = self.api.photos.getMessagesUploadServer()['upload_url']
        upload_data = requests.post(url=upload_url, files={'photo': ('image.png', image, 'image/png')}).json()
        image_data = self.api.photos.saveMessagesPhoto(**upload_data)
        owner_id = image_data[0]['owner_id']
        media_id = image_data[0]['id']
        attachment = f'photo{owner_id}_{media_id}'
        self.api.messages.send(
            attachment=attachment,
            random_id=random.randint(0, 2 ** 20),
            peer_id=user_id)

    # функция отправки маршрутов
    def send_routes(self, text_to_send, user_id):
        self.api.messages.send(
            message=text_to_send,
            random_id=random.randint(0, 2 ** 20),
            peer_id=user_id)

    # шаг отправки
    def send_step(self, step, user_id, text, context):
        if 'text' in step:
            self.send_text(text_to_send=step['text'].format(**context), user_id=user_id)
        if 'image' in step:
            handler = getattr(handlers, step['image'])
            image = handler(text=text, context=context)
            self.send_image(image=image, user_id=user_id)
        if 'choice' in step:
            handler = getattr(handlers, step['choice'])
            choices = handler(text=text, context=context)
            for i, choice in enumerate(choices, start=1):
                city_from = context['city_from']
                city_to = context['city_to']
                flight_time = choice[city_from][city_to][0]
                flight_board = choice[city_from][city_to][1]
                flight_date = choice[city_from][city_to][2]
                number_choice = str(i) + ') '
                Routes(number_choice=number_choice, flight_time=flight_time, city_from=city_from, city_to=city_to,
                       flight_board=flight_board, flight_date=flight_date)
            select = db.select('number_choice,flight_time,city_from,city_to,flight_board,flight_date FROM Routes')
            text_to_send = ' '.join(select[0]) + '\n' + ' '.join(select[1]) + '\n' + ' '.join(
                select[2]) + '\n' + ' '.join(
                select[3]) + '\n' + ' '.join(select[4]) + '\n'
            self.send_routes(text_to_send=text_to_send, user_id=user_id)


    # начало сценария
    def start_scenario(self, scenario_name, user_id, text):
        scenario = settings.SCENARIOS[scenario_name]
        first_step = scenario['first_step']
        step = scenario['steps'][first_step]
        self.send_step(step=step, user_id=user_id, text=text, context={})
        UserState(user_id=str(user_id), scenario_name=scenario_name, step_name=first_step, context={})

    # конец сценария
    def continue_scenario(self, text, state, user_id):
        steps = settings.SCENARIOS[state.scenario_name]['steps']
        step = steps[state.step_name]
        handler = getattr(handlers, step['handler'])
        if handler(text=text, context=state.context):
            # next_step
            if step['handler'] != 'handler_answer':
                self.walking_through_scenario(state=state, step=step, steps=steps, text=text, user_id=user_id)

            else:
                if state.context['answer'] == 'да':
                    self.walking_through_scenario(state=state, step=step, steps=steps, text=text, user_id=user_id)
                else:
                    next_step = step['failure_step']
                    state.delete()
                    self.send_step(step=step, user_id=user_id, text=text, context={})
                    UserState(user_id=str(user_id), scenario_name=state.scenario_name, step_name=next_step, context={})
        else:
            # retry_current_step
            text_to_send = step['failure_text'].format(**state.context)
            self.send_text(text_to_send=text_to_send, user_id=user_id)

    # движения по сценарию
    def walking_through_scenario(self, state, step, steps, text, user_id):
        next_step = steps[step['next_step']]
        self.send_step(step=next_step, user_id=user_id, text=text, context=state.context)
        if next_step['next_step']:
            # switch to next step
            state.step_name = step['next_step']
        else:
            # finish scenario and delete user states
            log.info(
                'Зарегистрирован  пользователь ФИО {name} следует из {city_from} в {city_to} телефон для контактов {phone} '.format(
                    **state.context))
            Registration(name=state.context['name'], city_from=state.context['city_from'],
                         city_to=state.context['city_to'],
                         phone=state.context['phone'])
            state.delete()


if __name__ == '__main__':
    configure_logging()
    bot = Bot(group_id=settings.GROUP_ID, token=settings.TOKEN)
    bot.run()

Solution

  • it helped me this command Routes.select(lambda p: p.id > 0 ).delete(bulk=True)