def test_set_from_cell_failure(self):
     """Test that wrong headers and fields raises Exceptions"""
     t = TestData()
     t.set_fk_labels_objects()
     # Test the value table format
     key = {'testitema': 'a1', 'testitemb': 'b1', 'testitemc': 'c1'}
     value = '4'
     column_field = 'value'
     # bad header field should raise a NoFieldError for header
     header = 'bad_header_name'
     try:
         t.set_from_cell(key, header, value, column_field)
     except NoFieldError as e:
         e_msg = str(e)
     self.assertEqual(e_msg, str(NoFieldError('bad_header_name', TestData)))
     # bad value_field should raise a NoItemError for value_field
     column_field = 'bad_column_field'
     header = 'value'
     try:
         t.set_from_cell(key, header, value, column_field)
     except NoFieldError as e:
         e_msg = str(e)
     self.assertEqual(e_msg, str(NoFieldError('bad_column_field',
                                              TestData)))
     # Bad header in multi-column should raise NoItemError for header
     key = {'testitema': 'a1', 'testitemb': 'b1'}
     value = '4'
     column_field = 'testitemc'
     header = 'bad_item_name'
     try:
         t.set_from_cell(key, header, value, column_field)
     except NoFieldError as e:
         e_msg = str(e)
     self.assertEqual(e_msg, str(NoItemError('bad_item_name', TestItemC)))
Exemple #2
0
 def test_table_save_POST_failure(self):
     """Test failure when saving data using POST edit method."""
     t = AssessTable(TestData, "")
     t.load(False, [])
     # Test bad decimal
     POST = {"('a1', 'b1', 'c1', 'value')": 'bad_decimal'}
     t.save_POST(POST)
     self.assertEqual(str(t.errors.pop()),
                      str(NotDecimalError('bad_decimal', TestData)))
     self.assertEqual(t.records[('a1', 'b1', 'c1', 'value')].get_value(),
                      '1,000')
     # Test bad POST key - item label
     POST = {"('bad_item', 'b1', 'c1', 'value')": '1'}
     t.save_POST(POST)
     self.assertEqual(
         str(t.errors.pop()),
         str(
             KeyNotFound("bad_item in ('bad_item', 'b1', 'c1', 'value')",
                         TestData)))
     self.assertEqual(t.records[('a1', 'b1', 'c1', 'value')].get_value(),
                      '1,000')
     # Test bad value field
     POST = {"('a1', 'b1', 'c1', 'bad_value_field')": '1'}
     t.save_POST(POST)
     self.assertEqual(str(t.errors.pop()),
                      str(NoFieldError('bad_value_field', TestData)))
     self.assertEqual(t.records[('a1', 'b1', 'c1', 'value')].get_value(),
                      '1,000')
 def test_set_from_record_failure(self):
     """Test that a record dict will update the model value."""
     t = TestData()
     t.set_fk_labels_objects()
     # Bad index name should raise NoFieldError
     r = {
         'bad_index_name': 'a1',
         'testitemb': 'b1',
         'testitemc': 'c1',
         'value': '4'
     }
     try:
         t.set_from_record_dict(r)
     except NoFieldError as e:
         e_msg = str(e)
     self.assertEqual(e_msg, str(NoFieldError('bad_index_name', TestData)))
     # Missing index fields in record dict should raise NoFieldError
     r = {'testitema': 'a1', 'testitemb': 'b1', 'value': '4'}
     try:
         t.set_from_record_dict(r)
     except NoFieldError as e:
         e_msg = str(e)
     self.assertEqual(e_msg, str(NoFieldError('testitemc', TestData)))
     # Bad value name should raise NoITemError
     r = {
         'testitema': 'bad_item',
         'testitemb': 'b1',
         'testitemc': 'c1',
         'value': '4'
     }
     try:
         t.set_from_record_dict(r)
     except NoItemError as e:
         e_msg = str(e)
     self.assertEqual(e_msg, str(NoItemError('bad_item', TestItemA)))
     # Missing value_field should raise NoFieldError
     r = {'testitema': 'a1', 'testitemb': 'b1', 'testitemc': 'c1'}
     try:
         t.set_from_record_dict(r)
     except NoFieldError as e:
         e_msg = str(e)
     self.assertEqual(e_msg, str(NoFieldError('value', TestData)))
Exemple #4
0
    def test_key_init_inconsistent_fields(self):
        """Testing internal check of fieldname consistency in __init__"""
        # Modify the class to add a bogus field name that is not in the DB
        TestMappings.index_fields.append('bad_field')
        tm = Keys(TestMappings)
        # Remove the field name again (or get horrible stuff in rest of tests)
        TestMappings.index_fields.remove('bad_field')
        # Careful if we end up going multi-language on error messages
        error_msg = str(NoFieldError('bad_field',TestMappings))
        self.assertEqual(str(tm.errors),error_msg)


        
Exemple #5
0
 def split_table_headers(self, table_headers) -> (list, list):
     """Split and check list of table headers to index + value headers."""
     table_index_headers = []
     table_value_headers = []
     # Split into index and value headers
     # Root out fields that are
     for field in table_headers:
         if field in self.index_headers:
             table_index_headers.append(field)
         elif field in self.value_headers:
             table_value_headers.append(field)
         else:
             raise NoFieldError(field, self.model)
     # Check that table index_fields are in the supplied index fields
     for field in self.index_headers:
         if field not in table_index_headers:
             raise NoFieldError(field, self.model)
     # No check that all table value_fields are in user value_fields
     # User is allowed to supply only a subset of value fields
     # However, at least one value field must be supplied
     if len(table_value_headers) == 0:
         raise NoFieldError(self.model.value_field, self.model)
     return table_index_headers, table_value_headers
Exemple #6
0
 def split_key_str(self, key_str: str) -> tuple:
     """Split a key string, check validity and return key tuple."""
     key_list = []
     key_labels = {}
     # Construct field names for model
     fields = self.model.index_fields.copy()
     fields.append(self.model.value_field)
     # Expected key string format is '(label1,label2,label3)'
     labels = key_str.strip("()").replace('\'', '').replace(" ",
                                                            "").split(',')
     # First part of the key string validation:
     # * Does splitting produce the right number of labels:
     if len(labels) != len(fields):
         raise KeyInvalid(key_str, self.model)
     # Second part of the key string validation:
     # * Are the labels present in list of index labels:
     fields_labels = dict(zip(fields, labels))
     for (field, label) in fields_labels.items():
         # label is the value_field name for non-index_fields
         if label == self.model.value_field:
             # add the value_field name to the key list
             key_list.append(label)
         # field is the index_field name for index fields
         elif field in self.model.index_fields:
             # For index_fields, label is the item label
             if label in self.indices_labels[field]:
                 # Add the index_field name to key list
                 key_list.append(label)
                 # Add the inde_field name / index_label to the key dict
                 key_labels[field] = label
             else:
                 # The label may not be an index item
                 raise KeyNotFound(label + ' in ' + key_str, self.model)
         else:
             # The field name in the POST dict may be incorrect
             # if it is not an item label nor the value_field name
             raise NoFieldError(label, self.model)
     # A key is a tuple of index item labels
     return tuple(key_list), key_labels
Exemple #7
0
 def test_parse_post_data_invalid(self):
     # Test that an invalid key length in POST results in an error and that
     # the POST entry is not added to the records
     tIO = AssessTableIO(TestData,delimiters)
     records = tIO.parse_POST(POST_invalid_length)
     key = list(POST_invalid_length.keys()).pop()
     self.assertEqual(str(tIO.errors.pop()),str(KeyInvalid(key, TestData)))
     self.assertEqual(records,{})
     # Test that an invalid key length in POST results in an error and that
     # the POST entry is not added to the records
     records = tIO.parse_POST(POST_invalid_label)
     key = 'bad_item in ' + list(POST_invalid_label.keys()).pop()
     self.assertEqual(str(tIO.errors.pop()),str(KeyNotFound(key, TestData)))
     self.assertEqual(records,{})
     # Test that an invalid value field name in POST results in an error 
     # and that the POST entry is not added to the records
     records = tIO.parse_POST(POST_invalid_value_field)
     error_msg = str(NoFieldError('bad_field', TestData))
     self.assertNotEqual(len(tIO.errors),0)
     if len(tIO.errors) > 0:
         self.assertEqual(str(tIO.errors.pop()),error_msg)
     self.assertEqual(records,{})
    def test_parse_csv_data_failure(self):
        """Test parsing of csv strings for mappings_model in TableIO - failures."""
        e1 = AssessError()
        e2 = AssessError()

        # Test malformed header - bad index header item
        ch = ['testitemBAD', 'testitemb', 'c1', 'c2']
        ct = ['testitema', 'testitemb', 'c1', 'c2']
        csv_data_string_c_bad_header = """testitemBAD\ttestitemb\tc1\tc2
a1\tb1\t1\t2
a2\tb1\t5\t6"""
        POST = {
            'column_field': 'testitemc',
            'csv_string': csv_data_string_c_bad_header
        }
        tIO = AssessTableIO(TestData, delimiters)
        tIO.parse_csv(POST)
        msg = str(NoFieldError('testitemBAD', TestData))
        e2 = CSVheaderMalformed(ch, ct, msg, TestData)
        e1 = tIO.errors.pop()
        self.assertEqual(str(e1), str(e2))
        # Test malformed header - missing index header item
        ch = ['testitemb', 'c1', 'c2']
        ct = ['testitema', 'testitemb', 'c1', 'c2']
        csv_data_string_c_bad_header = """testitemb\tc1\tc2
a1\tb1\t1\t2
a2\tb1\t5\t6"""
        POST = {
            'column_field': 'testitemc',
            'csv_string': csv_data_string_c_bad_header
        }
        tIO = AssessTableIO(TestData, delimiters)
        tIO.parse_csv(POST)
        msg = str(NoFieldError('testitema', TestData))
        e2 = CSVheaderMalformed(ch, ct, msg, TestData)
        e1 = tIO.errors.pop()
        self.assertEqual(str(e1), str(e2))
        # Test malformed header - missing value header item(s)
        ch = ['testitema', 'testitemb']
        ct = ['testitema', 'testitemb', 'c1', 'c2']
        csv_data_string_c_bad_header = """testitema\ttestitemb
a2\tb1\t5\t6"""
        POST = {
            'column_field': 'testitemc',
            'csv_string': csv_data_string_c_bad_header
        }
        tIO = AssessTableIO(TestData, delimiters)
        tIO.parse_csv(POST)
        msg = str(NoFieldError('value', TestData))
        e2 = CSVheaderMalformed(ch, ct, msg, TestData)
        e1 = tIO.errors.pop()
        self.assertEqual(str(e1), str(e2))
        # Test wrong line count: First dataline has 1 too many, last 1 too few
        csv_data_string_c_bad_count = """testitema\ttestitemb\tc1\tc2
a1\tb1\t1\t2\t99
a2\tb1\t5"""
        POST = {
            'column_field': 'testitemc',
            'csv_string': csv_data_string_c_bad_count
        }
        ch = ['testitema', 'testitemb', 'c1', 'c2']
        tIO = AssessTableIO(TestData, delimiters)
        tIO.parse_csv(POST)
        # One too many row columns
        row = ['a2', 'b1', '5']
        e2 = CSVwrongColumnCount(row, ch, '', TestData)
        e1 = tIO.errors.pop()
        self.maxDiff = None
        self.assertEqual(str(e1), str(e2))
        # Test wrong key
        row = ['a1', 'b1', '1', '2', '99']
        e2 = CSVwrongColumnCount(row, ch, '', TestData)
        e1 = tIO.errors.pop()
        self.maxDiff = None
        self.assertEqual(str(e1), str(e2))
        # Test bad index item in data row
        csv_data_string_c_bad_count = """testitema\ttestitemb\tc1\tc2
a1\tb1\t1\t2
BADITEM\tb1\t5\t6"""
        POST = {
            'column_field': 'testitemc',
            'csv_string': csv_data_string_c_bad_count
        }
        ch = ['testitema', 'testitemb', 'c1', 'c2']
        tIO = AssessTableIO(TestData, delimiters)
        tIO.parse_csv(POST)
        # One too many row columns
        row = ['BADITEM', 'b1', '5', '6']
        msg = str(NoItemError('BADITEM', TestItemA))
        e2 = CSVfieldNotFound(row, ch, msg, TestData)
        e1 = tIO.errors.pop()
        self.maxDiff = None
        self.assertEqual(str(e1), str(e2))
Exemple #9
0
    def __init__(self, model):
        """Set lookup dicts  for labels/ids """
        self.model = model
        foreignkey_columns = model.index_fields.copy()
        # Mappings model values are foreign keys, must be added to key lookup
        if self.model.model_type == 'mappings_model':
            foreignkey_columns.append(self.model.value_field)

        # Headers are for reading/displaying tables in other pivoting
        self.headers = []  # List of header strings
        # The union of item_headers and index_headers is equal to headers
        self.value_headers = []  # List of value header strings
        self.index_headers = []  # List of index header strings
        # Is table 1-column (value_field) or multi-column (column_field items)
        self.table_one_column = False

        # Lookup dicts for index field names and item ids and item labels
        self.indices_ids_labels = {}  # Dict of dicts {field: {id: label}, }
        self.indices_labels_ids = {}  # Dict of dicts {field: {label: id}, }
        self.indices_labels_objects = {
        }  # Dict of dicts {field: {label: object}, }

        self.indices_labels = {}  # Dict of lists {field: [label, ]}
        self.value_labels_ids = []  # Dict of value labels ids
        # OBS: Trying to return the indices items for specified archied
        # versions is going to be really messy. Current items are needed for
        # chekcing of user upload data integrity
        dimensions = []
        self.size = 1
        for column_name in foreignkey_columns:
            try:
                # Get the foreign key model items for each index in collection
                column_model = self.model._meta.get_field(
                    column_name).remote_field.model
            except:
                # Bad stuff will happen when self.index_field supplied in
                # app_name / models.py does not reflect the model's columns
                # ### OBS: Provide better error message from messages.py
                self.errors = NoFieldError(column_name, self.model)
            ids_labels = {}
            labels_ids = {}
            labels_objects = {}
            labels = []
            # Preferably the version filters should be imported from version.py
            # but this depend on keys so we cant.
            ### OBS!!! We restrict any table to use ONLY CURRENT VERSION ITEMS!
            ### Presently it's unclear how to load only items for given version
            fc = {'version_first__isnull': False, 'version_last__isnull': True}
            for item in column_model.objects.filter(**fc):
                ids_labels[item.id] = item.label
                labels_ids[item.label] = item.id
                labels_objects[item.label] = item
                labels.append(item.label)

            # Count dimension of the different indices
            s = len(labels)
            self.size = self.size * s
            dimensions.append(str(s))
            # Store the list and dicts in the collection object
            self.indices_ids_labels[column_name] = ids_labels
            self.indices_labels_ids[column_name] = labels_ids
            self.indices_labels_objects[column_name] = labels_objects
            self.indices_labels[column_name] = labels
            if column_name == self.model.value_field:
                self.value_labels_ids = labels_ids

        # Text string for description of table dimension
        self.dimension = "{" + " x ".join(dimensions) + "}"