예제 #1
0
    def test_request_sfdb_valid_sfdb_filepath(self, mocked_input):
        test_sfdb = ui.request_sfdb('')

        test_filepath = get_resource_filepath('test_duplicates.sfdb')
        expected_output = sfdb.SFDBContainer.from_file(test_filepath)

        self.assertEqual(expected_output, test_sfdb)
예제 #2
0
    def test_get_resource_filepath_resource_in_project(self):
        test_file = 'empty.sfdb'
        test_filepath = utilities.get_resource_filepath(test_file)

        dir1 = "sfdbtester"
        dir2 = "resources"
        self.assertTrue(dir1 in test_filepath)
        self.assertTrue(dir2 in test_filepath)
        self.assertTrue(test_file in test_filepath)
예제 #3
0
    def test_read_sfdb_from_file_single_entry(self):
        test_sfdb_filepath = get_resource_filepath('single_entry.sfdb')

        read_sfdb_lines = SFDBContainer.read_sfdb_from_file(test_sfdb_filepath)

        expected_lines = [
            'ENCODING UTF8', 'INIT', 'TABLE	SFI_TESTTABLE',
            'COLUMNS	COLUMN1	COLUMN2	COLUMN3', 'INSERT', 'val1	val2	val3'
        ]
        self.assertEqual(expected_lines, read_sfdb_lines)
예제 #4
0
    def test_read_sfdb_from_file_only_header(self):
        test_sfdb_filepath = get_resource_filepath('only_header.sfdb')

        read_sfdb_lines = SFDBContainer.read_sfdb_from_file(test_sfdb_filepath)

        expected_lines = [
            'ENCODING UTF8', 'INIT', 'TABLE	SFI_TESTTABLE',
            'COLUMNS	COLUMN1	COLUMN2	COLUMN3', 'INSERT'
        ]
        self.assertEqual(expected_lines, read_sfdb_lines)
예제 #5
0
    def test_check_content_format_wrong_content(self):
        wrong_content_format_filepath = get_resource_filepath(
            'wrong_content_format.sfdb')
        test_sfdb = sfdb.SFDBContainer.from_file(wrong_content_format_filepath)

        faulty_lines = sc.check_content_format(test_sfdb)

        expected_output = [(1, ['val1', 'val2']), (2, ['val1']),
                           (3, ['val1', 'val2', 'val3', 'val4']),
                           (4, ['val1', 'val2    val3'])]
        self.assertEqual(expected_output, faulty_lines)
예제 #6
0
    def test_check_for_duplicates_with_duplicates(self):
        no_duplicates_sfdb_filepath = get_resource_filepath(
            'test_duplicates.sfdb')
        test_sfdb = sfdb.SFDBContainer.from_file(no_duplicates_sfdb_filepath)

        faulty_lines = sc.check_for_duplicates(test_sfdb)

        expected_output = [(np.array([1, 2], dtype='int32'),
                            np.array(['val4', 'val5', 'val6']))]
        np.testing.assert_array_equal(expected_output[0][0],
                                      faulty_lines[0][0])
        np.testing.assert_array_equal(expected_output[0][1],
                                      faulty_lines[0][1])
예제 #7
0
    def test_write_to_file_valid_filepath(self):
        test_output_filepath = get_resource_filepath('tempfile.sfdb')
        test_sfdb = create_test_sfdbcontainer()

        test_sfdb.write_to_file(test_output_filepath)

        with open(test_output_filepath) as f:
            output = f.readlines()
        expected_output = [
            'ENCODING UTF8\n', 'INIT\n', 'TABLE	SMALL_TEST\n',
            'COLUMNS	COLUMN1	COLUMN2\n', 'INSERT\n', 'val1	val2\n',
            'val3	val4\n'
        ]
        self.assertEqual(expected_output, output)
예제 #8
0
    def test_write_with_duplicates(self):
        test_output_filepath = get_resource_filepath('tempfile.sfdb')
        test_entries = [['1', '2'], ['1', '2'], ['3', '4'], ['3', '4']]
        test_sfdb = create_test_sfdbcontainer(entries=test_entries)

        test_sfdb.write_to_file(test_output_filepath, remove_duplicates=True)

        with open(test_output_filepath) as f:
            output = f.readlines()
        expected_output = [
            'ENCODING UTF8\n', 'INIT\n', 'TABLE	SMALL_TEST\n',
            'COLUMNS	COLUMN1	COLUMN2\n', 'INSERT\n', '1	2\n', '3	4\n'
        ]

        self.assertEqual(expected_output, output)
예제 #9
0
    def test_check_excel_autoformatting_excel_formatted_sfdb(self):
        excel_formatted_sfdb_filepath = get_resource_filepath(
            'excel_formatting.sfdb')
        test_sfdb = sfdb.SFDBContainer.from_file(excel_formatted_sfdb_filepath)

        faulty_lines = sc.check_excel_autoformatting(test_sfdb)

        expected_output1 = (0, 0, np.array(['4.3E+04', 'val2'], dtype='<U8'))
        self.assertEqual(expected_output1[0], faulty_lines[0][0])
        self.assertEqual(expected_output1[1], faulty_lines[0][1])
        np.testing.assert_array_equal(faulty_lines[0][2], expected_output1[2])

        expected_output2 = (1, 1, np.array(['val1', '1.23E+08'], dtype='<U8'))
        self.assertEqual(expected_output2[0], faulty_lines[1][0])
        self.assertEqual(expected_output2[1], faulty_lines[1][1])
        np.testing.assert_array_equal(faulty_lines[1][2], expected_output2[2])
예제 #10
0
 def test_request_filepath_valid_filepath(self, mocked_input):
     filepath = ui.request_filepath('')
     expected_output = get_resource_filepath('empty.sfdb')
     self.assertEqual(expected_output, filepath)
     self.assertTrue(os.path.isfile(filepath))
예제 #11
0
 def test_get_resource_filepath_dir(self):
     test_file = 'test_dir'
     test_filepath = utilities.get_resource_filepath(test_file)
     contained_in_expected_output = '/sfdbtester/resources/test_dir'
     self.assertTrue(contained_in_expected_output in test_filepath)
예제 #12
0
 def test_get_resource_filepath_nonexistant_resource(self):
     test_file = 'ThisResourceDoesNotExist'
     with self.assertRaises(ValueError):
         utilities.get_resource_filepath(test_file)
예제 #13
0
class SQLTableSchema:
    """Part of an SFDB object. Defines the datatypes of the individual columns of an sfdb and the associated conditions
    entries need to fulfill. Datatypes are SQL datatypes. All already known/defined Tables are written in the
    sfdb_schemas.json resource. These defined requirements can then be used by checks to see whether all entries in
    the SFDB fulfill them."""
    sfdb_schema_file = get_resource_filepath('sfdb_schemas.json')

    def __init__(self, sql_table_name):
        self.table_name = sql_table_name
        self.column_properties = self._get_column_properties()

    @property
    def columns(self):
        """Returns a list of all columns in this sql_table_scheme"""
        return list(self.column_properties.keys())

    @columns.setter
    def columns(self, column_object_list):
        """Sets the list of column properties."""
        self.column_properties = column_object_list

    def __len__(self):
        """Return number of columns defined by the schema"""
        return len(self.column_properties)

    def __getitem__(self, column):
        """Return a column defined by the schema"""
        if column not in self.columns:
            raise ColumnError(f'Column {column} does not exist in table {self.table_name}!')
        return self.column_properties[column]

    def _get_column_properties(self):
        """Retrieves the SQL column definitions for the SFDB file based on user
        input if available.

        Returns:
            list: A list of tuples (ColumnName (string), Datatype (string),
                    Length (int), IsNullAllowed (bool))
            None: When users SQL column definitions are not already known to the
                    program (Other)"""
        known_sfdb_schemas = SQLTableSchema._get_known_sfdb_schemas()
        if self.table_name in known_sfdb_schemas:
            this_schema = known_sfdb_schemas[self.table_name]

            for column_name, column in this_schema.items():
                if column.datatype == 'datetime' or column.datatype == 'datetime2':
                    this_schema[column_name] = Column(column.name, column.datatype, 10, column.with_null)

            return this_schema

        return None

    @classmethod
    def _get_known_sfdb_schemas(cls):

        """Reads in the SFDB schemas of all known tables provided by the sfdb_schemas.json resource and returns them as
        dictionary"""
        with open(cls.sfdb_schema_file, mode='r') as schema_file:
            sfdb_schemas_json = json.load(schema_file)

        schemas_dict = {}
        for table_name, table_columns in sfdb_schemas_json.items():
            column_properties = {}

            for col in table_columns:
                column = Column(col['column_name'], col['datatype'], col['length'], col['with_null'])
                column_properties[col['column_name']] = column

            schemas_dict[table_name] = column_properties
        return schemas_dict

    def is_full_schema(self):
        """Checks whether the schema actually defines any columns"""
        return self.column_properties is not None

    def get_datatype_regex_pattern(self, column_name):
        """Generates a Pattern object of a regular expression that can match any
        column entry in an SQL table with this column definition of datatype and
        length. So far only covers nvarchar, int, bool, bit, datetime and datetime2.
        Datetime has not been tested yet.

        Parameters:
            column_name (string): The name of the sfdb column for which the regular expression is generated

        Returns:
            Pattern: Pattern object of a regular expression that matches any column
                        entry with the provided datatype and length
            None: When needed SQL datatype is not hard-coded in this function.
        """
        if column_name not in self.columns:
            raise ValueError('Column not in SQL table schema.')

        datatype = self.column_properties[column_name].datatype.lower()
        length = self.column_properties[column_name].length
        regex_string = None
        if datatype == 'nvarchar':
            regex_string = r'^.{0,' + str(length) + '}$'
        elif datatype == 'int':
            regex_string = r'^\d{1,' + str(length) + '}$'
        elif datatype == 'bool' or datatype.lower() == 'bit':
            regex_string = r'^[01]$'
        elif datatype == 'datetime2' or datatype.lower() == 'datetime':
            regex_string = r'^\d\d\d\d-\d\d-\d\d$'

        return re.compile(regex_string, re.IGNORECASE) if regex_string else regex_string
예제 #14
0
    def test_read_sfdb_from_file_empty_file(self):
        empty_sfdb_filepath = get_resource_filepath('empty.sfdb')

        with self.assertRaises(NotSFDBFileError):
            SFDBContainer.read_sfdb_from_file(empty_sfdb_filepath)
예제 #15
0
 def test___eq__string(self):
     test_sfdb = create_test_sfdbcontainer()
     with self.assertRaises(ValueError):
         test_sfdb.__eq__(get_resource_filepath('duplicates_test.sfdb'))
예제 #16
0
    def test_read_sfdb_from_file_wrong_header_sfdb(self):
        wrong_header_sfdb_filepath = get_resource_filepath('wrong_header.sfdb')

        with self.assertRaises(NotSFDBFileError):
            SFDBContainer.read_sfdb_from_file(wrong_header_sfdb_filepath)
예제 #17
0
class TestUserInput(ut.TestCase):
    def setUp(self) -> None:
        pass

    def test_request_regex_pattern_regex_input(self):
        with mock.patch('builtins.input', return_value=r'\d\d'):
            test_pattern = ui.request_regex_pattern('')
            test_string = '01'
            self.assertIsNotNone(test_pattern.match(test_string))

    @mock.patch('builtins.input', return_value=r'\l\d')
    @mock.patch('builtins.print',
                side_effect=[None, Exception('To Break the Loop!')])
    def test_request_regex_pattern_non_regex_input(self, mocked_input,
                                                   mocked_print):
        with self.assertRaises(Exception):
            ui.request_regex_pattern('')
            mocked_print.assert_called_with(
                'The input was not valid regular expression')

    @mock.patch('builtins.input', return_value='')
    @mock.patch('builtins.print')
    def test_request_regex_pattern_no_input(self, mocked_print, mocked_input):
        test_pattern = ui.request_regex_pattern('')
        mocked_print.assert_called_with('No Regex provided.')
        self.assertIsNone(test_pattern)

    @mock.patch('builtins.input', return_value='1 2 12')
    def test_request_list_of_int_list_of_int(self, mocked_input):
        int_list = ui.request_list_of_int('')
        expected_output = [1, 2, 12]
        self.assertEqual(expected_output, int_list)

    @mock.patch('builtins.input', return_value='1.3 2.4 12.5')
    @mock.patch('builtins.print', side_effect=Exception('Break The Loop!'))
    def test_request_list_of_int_list_of_float(self, mocked_print,
                                               mocked_input):
        with self.assertRaises(Exception):
            ui.request_list_of_int('')
        mocked_print.assert_called_with(
            f"!WARNING! The following entries are not integers :\n1.3  2.4  12.5"
        )

    @mock.patch('builtins.input', return_value='a bc def')
    @mock.patch('builtins.print', side_effect=Exception('Break The Loop!'))
    def test_request_list_of_int_list_of_string(self, mocked_print,
                                                mocked_input):
        with self.assertRaises(Exception):
            ui.request_list_of_int('')
        mocked_print.assert_called_with(
            f"!WARNING! The following entries are not integers :\na  bc  def")

    @mock.patch('builtins.input', return_value='')
    @mock.patch('builtins.print')
    def test_request_list_of_int_empty_string(self, mocked_print,
                                              mocked_input):
        ui.request_list_of_int('')
        mocked_print.assert_called_with(f"No list of numbers provided.")

    @mock.patch('builtins.input', return_value='1 2 3')
    @mock.patch('builtins.print', side_effect=Exception('Break The Loop!'))
    def test_request_list_of_int_list_of_int_below_min(self, mocked_print,
                                                       mocked_input):
        with self.assertRaises(Exception):
            ui.request_list_of_int('', min_value=2)
        mocked_print.assert_called_with(
            f"!WARNING! The following entries are below the allowed minimum of 2:\n1"
        )

    @mock.patch('builtins.input', return_value='1 2 3')
    @mock.patch('builtins.print', side_effect=Exception('Break The Loop!'))
    def test_request_list_of_int_list_of_int_above_max(self, mocked_print,
                                                       mocked_input):
        with self.assertRaises(Exception):
            ui.request_list_of_int('', max_value=2)
        mocked_print.assert_called_with(
            f"!WARNING! The following entries are above the allowed maximum of 2 :\n3"
        )

    @mock.patch('builtins.input', return_value='1 2 3')
    def test_request_list_of_int_list_of_int_between_min_max(
            self, mocked_input):
        int_list = ui.request_list_of_int('', min_value=0, max_value=4)
        expected_output = [1, 2, 3]
        self.assertEqual(expected_output, int_list)

    @mock.patch('builtins.input', return_value='a bc def')
    def test_request_items_of_list_valid_items(self, mocked_input):
        test_items = ['a', 'bc', 'gh', 'def']
        item_list = ui.request_items_of_list('', test_items)
        expected_output = ['a', 'bc', 'def']
        self.assertEqual(expected_output, item_list)

    @mock.patch('builtins.input', return_value='')
    def test_request_items_of_list_no_items(self, mocked_input):
        test_items = ['a', 'bc', 'gh', 'def']
        item_list = ui.request_items_of_list('', test_items)
        expected_output = []
        self.assertEqual(expected_output, item_list)

    @mock.patch('builtins.input', return_value='ij')
    @mock.patch('builtins.print', side_effect=Exception('Break The Loop!'))
    def test_request_items_of_list_invalid_items(self, mocked_print,
                                                 mocked_input):
        with self.assertRaises(Exception):
            test_items = ['a', 'bc', 'gh', 'def']
            ui.request_items_of_list('', test_items)
        mocked_print.assert_called_with(
            f"!WARNING! The following entries are not in the list of possible items:\nij"
        )

    @mock.patch('builtins.input', return_value='')
    def test_request_filepath_empty_string(self, mocked_input):
        filepath = ui.request_filepath('')
        expected_output = ''
        self.assertEqual(expected_output, filepath)

    @mock.patch('builtins.input', return_value='5')
    @mock.patch('builtins.print', side_effect=Exception('Break The Loop!'))
    def test_request_filepath_int(self, mocked_print, mocked_input):
        with self.assertRaises(Exception):
            ui.request_filepath('')
        mocked_print.assert_called_with(f"5 is not a valid filepath.")

    @mock.patch('builtins.input',
                return_value=
                f"{get_resource_filepath('empty.sfdb')}_invalid_path_addition")
    @mock.patch('builtins.print', side_effect=Exception('Break The Loop!'))
    def test_request_invalid_filepath(self, mocked_print, mocked_input):
        with self.assertRaises(Exception):
            ui.request_filepath('')
        mocked_print.assert_called_with(
            f"{get_resource_filepath('empty.sfdb')}_invalid_path_addition "
            f"is not a valid filepath.")

    @mock.patch('builtins.input',
                return_value=get_resource_filepath('empty.sfdb'))
    def test_request_filepath_valid_filepath(self, mocked_input):
        filepath = ui.request_filepath('')
        expected_output = get_resource_filepath('empty.sfdb')
        self.assertEqual(expected_output, filepath)
        self.assertTrue(os.path.isfile(filepath))

    @mock.patch('builtins.input',
                return_value=f"{get_resource_filepath('test_duplicates.sfdb')}"
                )
    def test_request_sfdb_valid_sfdb_filepath(self, mocked_input):
        test_sfdb = ui.request_sfdb('')

        test_filepath = get_resource_filepath('test_duplicates.sfdb')
        expected_output = sfdb.SFDBContainer.from_file(test_filepath)

        self.assertEqual(expected_output, test_sfdb)

    @mock.patch('builtins.input',
                return_value=f"{get_resource_filepath('empty.sfdb')}")
    def test_request_sfdb_valid_filepath_to_invalid_sfdb(self, mocked_input):
        with self.assertRaises(sfdb.NotSFDBFileError):
            ui.request_sfdb('')

    @mock.patch('builtins.print', side_effect=Exception('Break The Loop!'))
    @mock.patch('builtins.input',
                return_value=
                f"{get_resource_filepath('empty.sfdb')}_invalid_path_addition")
    def test_request_sfdb_invalid_filepath(self, mocked_input, mocked_print):
        with self.assertRaises(Exception):
            ui.request_filepath('')
        mocked_print.assert_called_with(
            f"{get_resource_filepath('empty.sfdb')}_invalid_path_addition "
            f"is not a valid filepath.")

    @mock.patch('builtins.input', return_value="")
    def test_request_sfdb_empty_filepath(self, mocked_input):
        test_sfdb = ui.request_sfdb('')
        self.assertIsNone(test_sfdb)
예제 #18
0
def configurate_logger(log_filepath):
    logging.addLevelName(LOGFILE_LEVEL, 'LOGFILE')
    logging.log_filepath = log_filepath

    config_file = get_resource_filepath('logging.cfg')
    logging.config.fileConfig(config_file)