<commit_before>#
# This file is part of pygimplib.
#
# Copyright (C) 2014, 2015 khalim19 <<EMAIL>>
#
# pygimplib is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# pygimplib is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with pygimplib.  If not, see <http://www.gnu.org/licenses/>.
#

"""
This module tests the `pgsetting` and `pgsettingpresenter` modules.
"""

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals

str = unicode

import os
import unittest

import gimpenums

from ..lib import mock

from . import gimpmocks
from .. import pgpath
from .. import pgsetting
from .. import pgsettingpresenter
from .. import pgsettingpersistor
from .. import pgsettingsources

#===============================================================================

LIB_NAME = ".".join(__name__.split(".")[:-2])

#===============================================================================


class MockGuiWidget(object):
  
  def __init__(self, value):
    self.value = value
    self.enabled = True
    self.visible = True
    
    self._signal = None
    self._event_handler = None
  
  def connect(self, signal, event_handler):
    self._signal = signal
    self._event_handler = event_handler
  
  def disconnect(self):
    self._signal = None
    self._event_handler = None
  
  def set_value(self, value):
    self.value = value
    if self._event_handler is not None:
      self._event_handler()


class MockGuiWidgetAlternate(MockGuiWidget):
  pass


class MockCheckbox(MockGuiWidget):
  pass


class MockSettingPresenter(pgsettingpresenter.SettingPresenter):
  
  def get_enabled(self):
    return self._element.enabled
  
  def set_enabled(self, value):
    self._element.enabled = value

  def get_visible(self):
    return self._element.visible
  
  def set_visible(self, value):
    self._element.visible = value
  
  def _create_gui_element(self, setting):
    return MockGuiWidget(setting.value)
  
  def _get_value(self):
    return self._element.value
  
  def _set_value(self, value):
    self._element.value = value
  
  def _connect_value_changed_event(self):
    self._element.connect(self._VALUE_CHANGED_SIGNAL, self._on_value_changed)
  
  def _disconnect_value_changed_event(self):
    self._element.disconnect()


class MockSettingPresenterWithValueChangedSignal(MockSettingPresenter):
  
  _VALUE_CHANGED_SIGNAL = "changed"


class MockSettingPresenterWithoutGuiElementCreation(MockSettingPresenter):
  
  def _create_gui_element(self, setting):
    return None


class MockCheckboxPresenter(MockSettingPresenter):
  
  def _create_gui_element(self, setting):
    return MockCheckbox(setting.value)


class MockYesNoToggleButtonPresenter(MockSettingPresenter):
  pass


#===============================================================================


class MockSetting(pgsetting.Setting):
  
  _ALLOWED_EMPTY_VALUES = [""]
  
  def _init_error_messages(self):
    self._error_messages['invalid_value'] = "value cannot be None or an empty string"
  
  def _validate(self, value):
    if value is None or value == "":
      raise pgsetting.SettingValueError(self._error_messages['invalid_value'])


class MockSettingRegistrableToPdb(MockSetting):

  _ALLOWED_PDB_TYPES = [pgsetting.SettingPdbTypes.string]


class MockSettingWithGui(MockSetting):
  
  _ALLOWED_GUI_TYPES = [MockCheckboxPresenter, MockSettingPresenter,
                        MockSettingPresenterWithValueChangedSignal,
                        MockSettingPresenterWithoutGuiElementCreation]


def on_file_extension_changed(file_extension, ignore_invisible):
  if file_extension.value == "png":
    ignore_invisible.set_value(False)
    ignore_invisible.gui.set_enabled(True)
  else:
    ignore_invisible.set_value(True)
    ignore_invisible.gui.set_enabled(False)


def on_file_extension_changed_with_autocrop(file_extension, autocrop):
  if file_extension.value == "png":
    autocrop.gui.set_visible(True)
  else:
    autocrop.gui.set_visible(False)


def on_autocrop_changed(autocrop, file_extension):
  if autocrop.value:
    file_extension.set_value("jpg")


#===============================================================================


class TestSetting(unittest.TestCase):
  
  def setUp(self):
    self.setting = MockSetting('file_extension', "png")
  
  def test_str(self):
    self.assertEqual(str(self.setting), "<MockSetting 'file_extension'>")
  
  def test_invalid_default_value_raises_error(self):
    with self.assertRaises(pgsetting.SettingDefaultValueError):
      MockSetting('setting', None)
  
  def test_empty_value_as_default_value(self):
    try:
      MockSetting('setting', "")
    except pgsetting.SettingDefaultValueError:
      self.fail("SettingDefaultValueError should not be raised - default value is an empty value")
  
  def test_assign_empty_value_not_allowed(self):
    with self.assertRaises(pgsetting.SettingValueError):
      self.setting.set_value("")
  
  def test_assign_empty_value_allowed(self):
    setting = MockSetting('setting', "", allow_empty_values=True)
    setting.set_value("")
    self.assertEqual(setting.value, "")
  
  def test_value_invalid_assignment_operation(self):
    with self.assertRaises(AttributeError):
      self.setting.value = "jpg"
  
  def test_auto_generated_display_name(self):
    self.assertEqual(MockSetting('this_is_a_setting', "png").display_name, "This is a setting")
  
  def test_description_from_display_name_with_mnemonics(self):
    setting = MockSetting('setting', "default value", display_name="_Setting")
    self.assertEqual(setting.display_name, "_Setting")
    self.assertEqual(setting.description, "Setting")
  
  def test_custom_error_messages(self):
    setting = MockSetting('setting', "")
    
    setting_with_custom_error_messages = MockSetting(
      'setting', "", error_messages={'invalid_value': "this should override the original error message",
                                     'custom_message': "custom message"})
    self.assertIn('custom_message', setting_with_custom_error_messages.error_messages)
    self.assertNotEqual(setting.error_messages['invalid_value'],
                        setting_with_custom_error_messages.error_messages['invalid_value'])
  
  def test_pdb_type_automatic_is_registrable(self):
    setting = MockSettingRegistrableToPdb('file_extension', "png", pdb_type=pgsetting.SettingPdbTypes.string)
    self.assertTrue(setting.can_be_registered_to_pdb())
  
  def test_pdb_type_automatic_is_not_registrable(self):
    setting = MockSetting('file_extension', "png")
    self.assertFalse(setting.can_be_registered_to_pdb())
  
  def test_invalid_pdb_type_raises_error(self):
    with self.assertRaises(ValueError):
      MockSetting('file_extension', "png", pdb_type=pgsetting.SettingPdbTypes.string)
  
  def test_reset_resets_setting_to_default_value(self):
    self.setting.set_value("jpg")
    self.setting.reset()
    self.assertEqual(self.setting.value, "png")
  
  def test_reset_default_value_container(self):
    setting = MockSetting('image_IDs_and_directories', {})
    setting.value[1] = "image_directory"
    
    setting.reset()
    self.assertEqual(setting.value, {})
    
    setting.value[2] = "another_image_directory"
    
    setting.reset()
    self.assertEqual(setting.value, {})
  
  @mock.patch(LIB_NAME + ".pgsettingpersistor.SettingPersistor.load")
  def test_load(self, mock_setting_persistor_load):
    dummy_setting_source = object()
    self.setting.load([dummy_setting_source])
    self.assertTrue(mock_setting_persistor_load.called)
  
  @mock.patch(LIB_NAME + ".pgsettingpersistor.SettingPersistor.load")
  def test_load_default_source(self, mock_setting_persistor_load):
    dummy_setting_source = object()
    setting = MockSetting('image_IDs_and_directories', {}, setting_sources=[dummy_setting_source])
    setting.load()
    self.assertTrue(mock_setting_persistor_load.called)
  
  def test_load_no_default_no_parameter(self):
    with self.assertRaises(ValueError):
      self.setting.load()
  
  @mock.patch(LIB_NAME + ".pgsettingpersistor.SettingPersistor.save")
  def test_save(self, mock_setting_persistor_save):
    dummy_setting_source = object()
    self.setting.save([dummy_setting_source])
    self.assertTrue(mock_setting_persistor_save.called)
  
  @mock.patch(LIB_NAME + ".pgsettingpersistor.SettingPersistor.save")
  def test_save_default_source(self, mock_setting_persistor_save):
    dummy_setting_source = object()
    setting = MockSetting('image_IDs_and_directories', {}, setting_sources=[dummy_setting_source])
    setting.save()
    self.assertTrue(mock_setting_persistor_save.called)
  
  def test_save_no_default_no_parameter(self):
    with self.assertRaises(ValueError):
      self.setting.save()
  

#===============================================================================


class TestSettingEvents(unittest.TestCase):
  
  def setUp(self):
    self.setting = MockSetting('file_extension', "png")<commit_msg>pgsetting: Update tests<commit_after>#
# This file is part of pygimplib.
#
# Copyright (C) 2014, 2015 khalim19 <<EMAIL>>
#
# pygimplib is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# pygimplib is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with pygimplib.  If not, see <http://www.gnu.org/licenses/>.
#

"""
This module tests the `pgsetting` and `pgsettingpresenter` modules.
"""

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals

str = unicode

import os
import unittest

import gimpenums

from ..lib import mock

from . import gimpmocks
from .. import pgpath
from .. import pgsetting
from .. import pgsettingpresenter
from .. import pgsettingpersistor
from .. import pgsettingsources

#===============================================================================

LIB_NAME = ".".join(__name__.split(".")[:-2])

#===============================================================================


class MockGuiWidget(object):
  
  def __init__(self, value):
    self.value = value
    self.enabled = True
    self.visible = True
    
    self._signal = None
    self._event_handler = None
  
  def connect(self, signal, event_handler):
    self._signal = signal
    self._event_handler = event_handler
  
  def disconnect(self):
    self._signal = None
    self._event_handler = None
  
  def set_value(self, value):
    self.value = value
    if self._event_handler is not None:
      self._event_handler()


class MockGuiWidgetAlternate(MockGuiWidget):
  pass


class MockCheckbox(MockGuiWidget):
  pass


class MockSettingPresenter(pgsettingpresenter.SettingPresenter):
  
  def get_enabled(self):
    return self._element.enabled
  
  def set_enabled(self, value):
    self._element.enabled = value

  def get_visible(self):
    return self._element.visible
  
  def set_visible(self, value):
    self._element.visible = value
  
  def _create_gui_element(self, setting):
    return MockGuiWidget(setting.value)
  
  def _get_value(self):
    return self._element.value
  
  def _set_value(self, value):
    self._element.value = value
  
  def _connect_value_changed_event(self):
    self._element.connect(self._VALUE_CHANGED_SIGNAL, self._on_value_changed)
  
  def _disconnect_value_changed_event(self):
    self._element.disconnect()


class MockSettingPresenterWithValueChangedSignal(MockSettingPresenter):
  
  _VALUE_CHANGED_SIGNAL = "changed"


class MockSettingPresenterWithoutGuiElementCreation(MockSettingPresenter):
  
  def _create_gui_element(self, setting):
    return None


class MockCheckboxPresenter(MockSettingPresenter):
  
  def _create_gui_element(self, setting):
    return MockCheckbox(setting.value)


class MockYesNoToggleButtonPresenter(MockSettingPresenter):
  pass


#===============================================================================


class MockSetting(pgsetting.Setting):
  
  _ALLOWED_EMPTY_VALUES = [""]
  
  def _init_error_messages(self):
    self._error_messages['invalid_value'] = "value cannot be None or an empty string"
  
  def _validate(self, value):
    if value is None or value == "":
      raise pgsetting.SettingValueError(self._error_messages['invalid_value'])


class MockSettingRegistrableToPdb(MockSetting):

  _ALLOWED_PDB_TYPES = [pgsetting.SettingPdbTypes.string]


class MockSettingWithGui(MockSetting):
  
  _ALLOWED_GUI_TYPES = [MockCheckboxPresenter, MockSettingPresenter,
                        MockSettingPresenterWithValueChangedSignal,
                        MockSettingPresenterWithoutGuiElementCreation]


def on_file_extension_changed(file_extension, ignore_invisible):
  if file_extension.value == "png":
    ignore_invisible.set_value(False)
    ignore_invisible.gui.set_enabled(True)
  else:
    ignore_invisible.set_value(True)
    ignore_invisible.gui.set_enabled(False)


def on_file_extension_changed_with_autocrop(file_extension, autocrop):
  if file_extension.value == "png":
    autocrop.gui.set_visible(True)
  else:
    autocrop.gui.set_visible(False)


def on_autocrop_changed(autocrop, file_extension):
  if autocrop.value:
    file_extension.set_value("jpg")


#===============================================================================


class TestSetting(unittest.TestCase):
  
  def setUp(self):
    self.setting = MockSetting('file_extension', "png")
  
  def test_str(self):
    self.assertEqual(str(self.setting), "<MockSetting 'file_extension'>")
  
  def test_invalid_default_value_raises_error(self):
    with self.assertRaises(pgsetting.SettingDefaultValueError):
      MockSetting('setting', None)
  
  def test_empty_value_as_default_value(self):
    try:
      MockSetting('setting', "")
    except pgsetting.SettingDefaultValueError:
      self.fail("SettingDefaultValueError should not be raised - default value is an empty value")
  
  def test_assign_empty_value_not_allowed(self):
    with self.assertRaises(pgsetting.SettingValueError):
      self.setting.set_value("")
  
  def test_assign_empty_value_allowed(self):
    setting = MockSetting('setting', "", allow_empty_values=True)
    setting.set_value("")
    self.assertEqual(setting.value, "")
  
  def test_value_invalid_assignment_operation(self):
    with self.assertRaises(AttributeError):
      self.setting.value = "jpg"
  
  def test_auto_generated_display_name(self):
    self.assertEqual(MockSetting('this_is_a_setting', "png").display_name, "This is a setting")
  
  def test_description_from_display_name_with_mnemonics(self):
    setting = MockSetting('setting', "default value", display_name="_Setting")
    self.assertEqual(setting.display_name, "_Setting")
    self.assertEqual(setting.description, "Setting")
  
  def test_custom_error_messages(self):
    setting = MockSetting('setting', "")
    
    setting_with_custom_error_messages = MockSetting(
      'setting', "", error_messages={'invalid_value': "this should override the original error message",
                                     'custom_message': "custom message"})
    self.assertIn('custom_message', setting_with_custom_error_messages.error_messages)
    self.assertNotEqual(setting.error_messages['invalid_value'],
                        setting_with_custom_error_messages.error_messages['invalid_value'])
  
  def test_pdb_type_automatic_is_registrable(self):
    setting = MockSettingRegistrableToPdb('file_extension', "png", pdb_type=pgsetting.SettingPdbTypes.string)
    self.assertTrue(setting.can_be_registered_to_pdb())
  
  def test_pdb_type_automatic_is_not_registrable(self):
    setting = MockSetting('file_extension', "png")
    self.assertFalse(setting.can_be_registered_to_pdb())
  
  def test_invalid_pdb_type_raises_error(self):
    with self.assertRaises(ValueError):
      MockSetting('file_extension', "png", pdb_type=pgsetting.SettingPdbTypes.string)
  
  def test_reset_resets_setting_to_default_value(self):
    self.setting.set_value("jpg")
    self.setting.reset()
    self.assertEqual(self.setting.value, "png")
  
  def test_reset_default_value_container(self):
    setting = MockSetting('image_IDs_and_directories', {})
    setting.value[1] = "image_directory"
    
    setting.reset()
    self.assertEqual(setting.value, {})
    
    setting.value[2] = "another_image_directory"
    
    setting.reset()
    self.assertEqual(setting.value, {})
  
  @mock.patch(LIB_NAME + ".pgsettingpersistor.SettingPersistor.load")
  def test_load(self, mock_setting_persistor_load):
    dummy_setting_source = object()
    self.setting.load([dummy_setting_source])
    self.assertTrue(mock_setting_persistor_load.called)
  
  @mock.patch(LIB_NAME + ".pgsettingpersistor.SettingPersistor.load")
  def test_load_default_source(self, mock_setting_persistor_load):
    dummy_setting_source = object()
    setting = MockSetting('image_IDs_and_directories', {}, setting_sources=[dummy_setting_source])
    setting.load()
    self.assertTrue(mock_setting_persistor_load.called)
  
  @mock.patch(LIB_NAME + ".pgsettingpersistor.SettingPersistor.load")
  def test_load_default_source_overridden_by_parameter(self, mock_setting_persistor_load):
    dummy_setting_source_default = object()
    setting = MockSetting('image_IDs_and_directories', {}, setting_sources=[dummy_setting_source_default])
    dummy_setting_source_parameter = object()
    setting.load([dummy_setting_source_parameter])
    self.assertTrue(mock_setting_persistor_load.called)
    self.assertIn(dummy_setting_source_parameter, mock_setting_persistor_load.call_args[0][1])
    self.assertNotIn(dummy_setting_source_default, mock_setting_persistor_load.call_args[0][1])
  
  def test_load_no_default_source_no_parameter(self):
    with self.assertRaises(ValueError):
      self.setting.load()
  
  @mock.patch(LIB_NAME + ".pgsettingpersistor.SettingPersistor.save")
  def test_save(self, mock_setting_persistor_save):
    dummy_setting_source = object()
    self.setting.save([dummy_setting_source])
    self.assertTrue(mock_setting_persistor_save.called)
  
  @mock.patch(LIB_NAME + ".pgsettingpersistor.SettingPersistor.save")
  def test_save_default_source(self, mock_setting_persistor_save):
    dummy_setting_source = object()
    setting = MockSetting('image_IDs_and_directories', {}, setting_sources=[dummy_setting_source])
    setting.save()
    self.assertTrue(mock_setting_persistor_save.called)
  
  @mock.patch(LIB_NAME + ".pgsettingpersistor.SettingPersistor.save")
  def test_save_default_source_overridden_by_parameter(self, mock_setting_persistor_save):
    dummy_setting_source_default = object()
    setting = MockSetting('image_IDs_and_directories', {}, setting_sources=[dummy_setting_source_default])
    dummy_setting_source_parameter = object()
    setting.save([dummy_setting_source_parameter])
    self.assertTrue(mock_setting_persistor_save.called)
    self.assertIn(dummy_setting_source_parameter, mock_setting_persistor_save.call_args[0][1])
    self.assertNotIn(dummy_setting_source_default, mock_setting_persistor_save.call_args[0][1])
  
  def test_save_no_default_source_no_parameter(self):
    with self.assertRaises(ValueError):
      self.setting.save()
  

#===============================================================================


class TestSettingEvents(unittest.TestCase):
  
  def setUp(self):
    self.setting = MockSetting('file_extension', "png")
{'fraction_non_alphanumeric': 0.12878188649396877, 'fraction_numerical': 0.0017797112912794147, 'mean_word_length': 5.051151660185462, 'pattern_counts': {'":': 6, '<': 11, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2359818', 'n_tokens_mistral': 6129, 'n_tokens_neox': 5980, 'n_words': 1091}