コード例 #1
0
    def get_actions_to_perform(self, model, field):
        actions = [
            'add field with default',
            'update existing rows',
            'set not null for field',
            'drop default',
        ]

        # Checking maybe this column already exists
        # if so asking user what to do next
        column_info = self.get_column_info(model, field)

        if column_info is not None:
            existed_nullable, existed_type, existed_default = column_info

            questioner = InteractiveMigrationQuestioner()
            question_template = (
                'It look like column "{}" in table "{}" already exist with following '
                'parameters: TYPE: "{}", DEFAULT: "{}", NULLABLE: "{}".')
            question = question_template.format(
                field.name,
                model._meta.db_table,
                existed_type,
                existed_default,
                existed_nullable,
            )
            choices = (
                'abort migration',
                'drop column and run migration from beginning',
                'manually choose action to start from',
                'show how many rows still need to be updated',
                'mark operation as successful and proceed to next operation',
                'drop column and run migration from standard SchemaEditor',
            )

            result = questioner._choice_input(question, choices)
            if result == 1:
                sys.exit(1)
            elif result == 2:
                self.remove_field(model, field)
            elif result == 3:
                question = 'Now choose from which action process should continue'
                result = questioner._choice_input(question, actions)
                actions = actions[result - 1:]
            elif result == 4:
                question = 'Rows in table where column is null: "{}"'
                need_to_update = self.need_to_update(model=model, field=field)
                questioner._choice_input(question.format(need_to_update),
                                         ('Continue', ))
                return self.get_actions_to_perform(model, field)
            elif result == 5:
                actions = []
            elif result == 6:
                self.remove_field(model, field)
                super(ZeroDownTimeMixin, self).add_field(model, field)
                actions = []
        return actions
コード例 #2
0
    def get_actions_to_perform(self, model, field):
        actions = self.ADD_FIELD_WITH_DEFAULT_ACTIONS
        # Checking maybe this column already exists
        # if so asking user what to do next
        column_info = self.get_column_info(model, field)

        if column_info is not None:
            existed_nullable, existed_type, existed_default = column_info

            questioner = InteractiveMigrationQuestioner()

            question = self.RETRY_QUESTION_TEMPLATE.format(
                field.name,
                model._meta.db_table,
                existed_type,
                existed_default,
                existed_nullable,
            )

            result = questioner._choice_input(question, self.RETRY_CHOICES)
            if result == 1:
                sys.exit(1)
            elif result == 2:
                self.remove_field(model, field)
            elif result == 3:
                question = 'Now choose from which action process should continue'
                result = questioner._choice_input(question, actions)
                actions = actions[result - 1:]
            elif result == 4:
                question = 'Rows in table where column is null: "{}"'
                need_to_update = self.need_to_update(model=model, field=field)
                questioner._choice_input(question.format(need_to_update),
                                         ('Continue', ))
                return self.get_actions_to_perform(model, field)
            elif result == 5:
                actions = []
            elif result == 6:
                self.remove_field(model, field)
                super(ZeroDownTimeMixin, self).add_field(model, field)
                actions = []
        return actions
コード例 #3
0
class QuestionerHelperMethodsTests(SimpleTestCase):
    def setUp(self):
        self.prompt = OutputWrapper(StringIO())
        self.questioner = InteractiveMigrationQuestioner(
            prompt_output=self.prompt)

    @mock.patch('builtins.input', return_value='datetime.timedelta(days=1)')
    def test_questioner_default_timedelta(self, mock_input):
        value = self.questioner._ask_default()
        self.assertEqual(value, datetime.timedelta(days=1))

    @mock.patch('builtins.input', return_value='')
    def test_questioner_default_no_user_entry(self, mock_input):
        value = self.questioner._ask_default(
            default='datetime.timedelta(days=1)')
        self.assertEqual(value, datetime.timedelta(days=1))

    @mock.patch('builtins.input', side_effect=['', 'exit'])
    def test_questioner_no_default_no_user_entry(self, mock_input):
        with self.assertRaises(SystemExit):
            self.questioner._ask_default()
        self.assertIn(
            "Please enter some code, or 'exit' (without quotes) to exit.",
            self.prompt.getvalue(),
        )

    @mock.patch('builtins.input', side_effect=['bad code', 'exit'])
    def test_questioner_no_default_bad_user_entry_code(self, mock_input):
        with self.assertRaises(SystemExit):
            self.questioner._ask_default()
        self.assertIn('Invalid input: ', self.prompt.getvalue())

    @mock.patch('builtins.input', side_effect=['', 'n'])
    def test_questioner_no_default_no_user_entry_boolean(self, mock_input):
        value = self.questioner._boolean_input('Proceed?')
        self.assertIs(value, False)

    @mock.patch('builtins.input', return_value='')
    def test_questioner_default_no_user_entry_boolean(self, mock_input):
        value = self.questioner._boolean_input('Proceed?', default=True)
        self.assertIs(value, True)

    @mock.patch('builtins.input', side_effect=[10, 'garbage', 1])
    def test_questioner_bad_user_choice(self, mock_input):
        question = 'Make a choice:'
        value = self.questioner._choice_input(question, choices='abc')
        expected_msg = (f'{question}\n' f' 1) a\n' f' 2) b\n' f' 3) c\n')
        self.assertIn(expected_msg, self.prompt.getvalue())
        self.assertEqual(value, 1)
コード例 #4
0
class QuestionerHelperMethodsTests(SimpleTestCase):
    def setUp(self):
        self.prompt = OutputWrapper(StringIO())
        self.questioner = InteractiveMigrationQuestioner(prompt_output=self.prompt)

    @mock.patch("builtins.input", return_value="datetime.timedelta(days=1)")
    def test_questioner_default_timedelta(self, mock_input):
        value = self.questioner._ask_default()
        self.assertEqual(value, datetime.timedelta(days=1))

    @mock.patch("builtins.input", return_value="")
    def test_questioner_default_no_user_entry(self, mock_input):
        value = self.questioner._ask_default(default="datetime.timedelta(days=1)")
        self.assertEqual(value, datetime.timedelta(days=1))

    @mock.patch("builtins.input", side_effect=["", "exit"])
    def test_questioner_no_default_no_user_entry(self, mock_input):
        with self.assertRaises(SystemExit):
            self.questioner._ask_default()
        self.assertIn(
            "Please enter some code, or 'exit' (without quotes) to exit.",
            self.prompt.getvalue(),
        )

    @mock.patch("builtins.input", side_effect=["bad code", "exit"])
    def test_questioner_no_default_bad_user_entry_code(self, mock_input):
        with self.assertRaises(SystemExit):
            self.questioner._ask_default()
        self.assertIn("Invalid input: ", self.prompt.getvalue())

    @mock.patch("builtins.input", side_effect=["", "n"])
    def test_questioner_no_default_no_user_entry_boolean(self, mock_input):
        value = self.questioner._boolean_input("Proceed?")
        self.assertIs(value, False)

    @mock.patch("builtins.input", return_value="")
    def test_questioner_default_no_user_entry_boolean(self, mock_input):
        value = self.questioner._boolean_input("Proceed?", default=True)
        self.assertIs(value, True)

    @mock.patch("builtins.input", side_effect=[10, "garbage", 1])
    def test_questioner_bad_user_choice(self, mock_input):
        question = "Make a choice:"
        value = self.questioner._choice_input(question, choices="abc")
        expected_msg = f"{question}\n" f" 1) a\n" f" 2) b\n" f" 3) c\n"
        self.assertIn(expected_msg, self.prompt.getvalue())
        self.assertEqual(value, 1)