예제 #1
0
 def test_instance_is_reused(self):
     resource = EditableMock()
     resource.entity.body = dict(categories=TEST_CATEGORIES(),
                                 type='categorical')
     variable = Variable(resource, MagicMock())
     cat_list = variable.categories
     self.assertTrue(isinstance(cat_list, CategoryList))
예제 #2
0
 def test_edit_category_date(self):
     resource = EditableMock()
     resource.entity.body = dict(categories=TEST_CATEGORIES_WITH_DATE(),
                                 type='categorical')
     variable = Variable(resource, MagicMock())
     variable.categories[1].edit(date='2021-01-01')
     resource.entity._edit.assert_called_with(
         categories=[{
             'numeric_value': None,
             'selected': False,
             'id': 1,
             'missing': False,
             'name': 'Female',
             'date': '2021-01-01'
         }, {
             'numeric_value': None,
             'missing': False,
             'id': 2,
             'name': 'Male',
             'date': '2020-02-02'
         }, {
             'numeric_value': None,
             'missing': True,
             'id': -1,
             'name': 'No Data'
         }])
     resource.entity.refresh.assert_called_once()
     self.assertEqual(variable.categories[1].date, '2021-01-01')
예제 #3
0
    def test_reorder(self):
        resource = EditableMock()
        resource.entity.body = dict(categories=TEST_CATEGORIES(),
                                    type='categorical')
        variable = Variable(resource, MagicMock())
        variable.categories.order(2, -1, 1)

        # Reordered values
        resource.entity._edit.assert_called_with(categories=[{
            'numeric_value': None,
            'missing': False,
            'id': 2,
            'name': 'Male'
        }, {
            'numeric_value': None,
            'missing': True,
            'id': -1,
            'name': 'No Data'
        }, {
            'numeric_value': None,
            'missing': False,
            'id': 1,
            'name': 'Female'
        }])
        resource.entity.refresh.assert_called_once()
예제 #4
0
 def test_read_category_date(self):
     resource = EditableMock()
     resource.entity.body = dict(categories=TEST_CATEGORIES_WITH_DATE(),
                                 type='categorical')
     variable = Variable(resource, MagicMock())
     self.assertEqual(variable.categories[1].date, '2020-01-01')
     self.assertEqual(variable.categories[2].date, '2020-02-02')
     with self.assertRaises(KeyError):
         # The `No Data` category doesn't provide a `date field
         _ = variable.categories[3].date
예제 #5
0
    def test_edit_derived(self):
        resource = EditableMock()
        resource.entity.body = dict(
            categories=TEST_CATEGORIES(),
            type='categorical',
            derivation={'function': 'derivation_function'})
        variable = Variable(resource, MagicMock())

        error_msg = "Cannot edit categories on derived variables. Re-derive with the appropriate expression"
        with pytest.raises(TypeError, message=error_msg):
            variable.categories[1].edit(name='Mujer')

        # Try again with an empty derivation
        resource = EditableMock()
        resource.entity.body = dict(
            categories=TEST_CATEGORIES(),
            type='categorical',
            derivation={}  # Empty
        )
        variable = Variable(resource, MagicMock())
        variable.categories[1].edit(name='Mujer')
        resource.entity._edit.assert_called_with(categories=[{
            'numeric_value': None,
            'selected': False,
            'id': 1,
            'missing': False,
            'name': 'Mujer'
        }, {
            'numeric_value': None,
            'missing': False,
            'id': 2,
            'name': 'Male'
        }, {
            'numeric_value': None,
            'missing': True,
            'id': -1,
            'name': 'No Data'
        }])
예제 #6
0
 def test_validate_range_expression(self):
     test_map = {1: range(1, 5)}
     test_cats = {1: "China"}
     ds_res_mock = mock.MagicMock()
     variable_mock = mock.MagicMock()
     subvar_mock = mock.MagicMock(entity_url=subvar1_url)
     # mock the call to entity, this will happen on Variable.resource
     variable_mock.entity.subvariables.by.return_value = {
         'parent_1': subvar_mock,
         'parent_2': subvar_mock,
         'parent_3': subvar_mock,
         'parent_4': subvar_mock,
     }
     parent_var = Variable(variable_mock, ds_res_mock)
     modified_map = responses_from_map(parent_var, test_map, test_cats,
                                       'test', 'parent')
     # subvar_url * 4 because we used the same mock for all subvars
     assert modified_map[0]['combined_ids'] == [subvar1_url] * 4
예제 #7
0
 def test_delete_category(self):
     resource = EditableMock()
     resource.entity.body = dict(categories=TEST_CATEGORIES(),
                                 type='categorical')
     variable = Variable(resource, MagicMock())
     variable.categories[1].delete()
     # Calling edit without the one that we wanted to delete
     resource.entity._edit.assert_called_with(categories=[{
         'numeric_value': None,
         'missing': False,
         'id': 2,
         'name': 'Male'
     }, {
         'numeric_value': None,
         'missing': True,
         'id': -1,
         'name': 'No Data'
     }])
예제 #8
0
    def test_combine_categories_from_entity(self):
        resource = mock.MagicMock()
        resource.body = {'name': 'mocked_dataset'}
        entity_mock = mock.MagicMock()
        entity_mock.entity.self = var_url
        resource.variables.by.return_value = {
            'test': entity_mock
        }
        resource.variables.index = {}  # Var not present

        # mock a Tuple object
        tuple_mock = mock.MagicMock()
        tuple_mock.entity.self = var_url

        entity = Variable(tuple_mock, resource)
        ds = MutableDataset(resource)
        with pytest.raises(ValueError) as err:
            ds.combine_categorical(entity, CATEGORY_MAP, CATEGORY_NAMES, name='name', alias='alias')
        ds.resource.variables.create.assert_called_with(RECODES_PAYLOAD)
        assert 'Entity mocked_dataset has no (sub)variable' in str(err.value)
예제 #9
0
    def test_category_attribute_writes(self):
        resource = EditableMock()
        resource.entity.body = dict(
            categories=TEST_CATEGORIES(),
            type='categorical',
        )
        variable = Variable(resource, MagicMock())

        error_msg = "use the edit() method for mutating attributes"

        with pytest.raises(AttributeError) as excinfo:
            variable.categories[1].id = 42
        # nothing has changed
        assert variable.categories[1].id == 1
        assert str(excinfo.value) == "Can't edit attibute 'id'"

        with pytest.raises(AttributeError) as excinfo:
            variable.categories[1].name = 'forbidden'
        # nothing has changed
        assert variable.categories[1].name == 'Female'
        assert str(excinfo.value) == error_msg

        with pytest.raises(AttributeError) as excinfo:
            variable.categories[1].numeric_value = 42
        # nothing has changed
        assert variable.categories[1].numeric_value is None
        assert str(excinfo.value) == error_msg

        with pytest.raises(AttributeError) as excinfo:
            variable.categories[1].missing = True
        # nothing has changed
        assert variable.categories[1].missing is False
        assert str(excinfo.value) == error_msg

        with pytest.raises(AttributeError) as excinfo:
            variable.categories[1].selected = True
        # nothing has changed, default is False
        assert variable.categories[1].selected is False
        assert str(excinfo.value) == error_msg
예제 #10
0
 def test_category_dict_attribytes(self):
     resource = EditableMock()
     resource.entity.body = dict(categories=TEST_CATEGORIES(),
                                 type='categorical')
     variable = Variable(resource, MagicMock())
     # Does not have `date` unnecessarily
     assert variable.categories[1].as_dict() == {
         'id': 1,
         'missing': False,
         'name': 'Female',
         'numeric_value': None,
         'selected': False
     }
     variable.categories[1].edit(date="1990-02-04")
     # Contains .date if needed
     assert variable.categories[1].as_dict() == {
         'id': 1,
         'missing': False,
         'name': 'Female',
         'numeric_value': None,
         'selected': False,
         "date": "1990-02-04"
     }
예제 #11
0
    def test_recode_multiple_responses(self, get_dataset_mock):
        dataset_id = '123'
        categories = [{
            'numeric_value': 1,
            'selected': True,
            'id': 1,
            'name': 'selected',
            'missing': False
        }, {
            'numeric_value': 2,
            'selected': False,
            'id': 2,
            'name': 'not selected',
            'missing': False
        }, {
            'numeric_value': 9,
            'missing': True,
            'id': 9,
            'name': 'not asked'
        }, {
            'numeric_value': 8,
            'missing': True,
            'id': 8,
            'name': 'skipped'
        }]
        var_res = Entity(
            mock.MagicMock(),
            **{
                'element':
                'shoji:entity',
                'self':
                'http://test.crunch.io/api/datasets/%s/variables/0001/' %
                dataset_id,
                # needed in order to simulate a Tuple, now Variable is inited with Tuple
                'entity_url':
                'http://test.crunch.io/api/datasets/%s/variables/0001/' %
                dataset_id,
                'body': {
                    'name':
                    'Q1',
                    'subreferences': [{
                        'alias': 'Q1_1',
                        'is_subvar': True,
                        'name': 'One'
                    }, {
                        'alias': 'Q1_2',
                        'is_subvar': True,
                        'name': 'Two'
                    }, {
                        'alias': 'Q1_3',
                        'is_subvar': True,
                        'name': 'Three'
                    }],
                    'missing_reasons': {
                        'skipped': 8,
                        'not asked': 9
                    },
                    'alias':
                    'Q1',
                    'subvariables': [
                        'http://test.crunch.io/api/datasets/%s/variables/0001/subvariables/000a/'
                        % dataset_id,
                        'http://test.crunch.io/api/datasets/%s/variables/0001/subvariables/000b/'
                        % dataset_id,
                        'http://test.crunch.io/api/datasets/%s/variables/0001/subvariables/000c/'
                        % dataset_id
                    ],
                    'dataset_id':
                    dataset_id,
                    'type':
                    'multiple_response',
                    'id':
                    '0001',
                    'categories':
                    categories,
                    'description':
                    'Multiple Response Example'
                }
            })
        table_mock = mock.MagicMock(
            metadata={
                '00001': {
                    'id': '00001',
                    'alias': 'sexuality',
                    'type': 'categorical',
                    'categories': categories
                }
            })
        ds_res = mock.MagicMock()
        Variable(var_res, ds_res)
        ds_res.self = dataset_url
        ds_res.follow.return_value = table_mock
        dataset = Dataset(ds_res)
        subvar_mock = mock.MagicMock()
        subvar_mock.self = var_url
        subvar_mock.id = 'subvar'
        subvariables = {
            'Q1_1': subvar_mock,
            'Q1_2': subvar_mock,
            'Q1_3': subvar_mock,
        }

        dataset.create_categorical(
            [{
                'id': 1,
                'name': 'Q1_recoded_1',
                'case': mr_in(var_url, 'Q1', [1, 2], subvariables)
            }, {
                'id': 2,
                'name': 'Q1_recoded_2',
                'case': mr_in(var_url, 'Q1', [3], subvariables)
            }],
            alias='Q1_recoded',
            name='Q1_recoded',
            multiple=True)

        # Test how the recoded var was created.
        ds_res.variables.create.assert_called_with({
            'element': 'shoji:entity',
            'body': {
                'name': 'Q1_recoded',
                'description': '',
                'alias': 'Q1_recoded',
                'derivation': {
                    'function':
                    'array',
                    'args': [{
                        'function':
                        'select',
                        'args': [{
                            'map': {
                                '0001': {
                                    'function':
                                    'case',
                                    'args': [{
                                        'column': [1, 2],
                                        'type': {
                                            'value': {
                                                'class':
                                                'categorical',
                                                'categories': [{
                                                    'selected':
                                                    True,
                                                    'numeric_value':
                                                    None,
                                                    'missing':
                                                    False,
                                                    'id':
                                                    1,
                                                    'name':
                                                    'Selected'
                                                }, {
                                                    'selected':
                                                    False,
                                                    'numeric_value':
                                                    None,
                                                    'missing':
                                                    False,
                                                    'id':
                                                    2,
                                                    'name':
                                                    'Not selected'
                                                }]
                                            }
                                        }
                                    }, {
                                        'function':
                                        'any',
                                        'args': [{
                                            'variable':
                                            'http://test.crunch.io/api/datasets/123/variables/0001/'
                                        }, {
                                            'column': ['subvar', 'subvar']
                                        }]
                                    }],
                                    'references': {
                                        'alias': 'Q1_recoded_1',
                                        'name': 'Q1_recoded_1'
                                    }
                                },
                                '0002': {
                                    'function':
                                    'case',
                                    'args': [{
                                        'column': [1, 2],
                                        'type': {
                                            'value': {
                                                'class':
                                                'categorical',
                                                'categories': [{
                                                    'selected':
                                                    True,
                                                    'numeric_value':
                                                    None,
                                                    'missing':
                                                    False,
                                                    'id':
                                                    1,
                                                    'name':
                                                    'Selected'
                                                }, {
                                                    'selected':
                                                    False,
                                                    'numeric_value':
                                                    None,
                                                    'missing':
                                                    False,
                                                    'id':
                                                    2,
                                                    'name':
                                                    'Not selected'
                                                }]
                                            }
                                        }
                                    }, {
                                        'function':
                                        'any',
                                        'args': [{
                                            'variable':
                                            'http://test.crunch.io/api/datasets/123/variables/0001/'
                                        }, {
                                            'column': ['subvar']
                                        }]
                                    }],
                                    'references': {
                                        'alias': 'Q1_recoded_2',
                                        'name': 'Q1_recoded_2'
                                    }
                                }
                            }
                        }]
                    }]
                }
            }
        })
예제 #12
0
    def test_edit_category(self):
        resource = EditableMock()
        resource.entity.body = dict(categories=TEST_CATEGORIES(),
                                    type='categorical')
        variable = Variable(resource, MagicMock())
        variable.categories[1].edit(name='Mujer')
        resource.entity._edit.assert_called_with(categories=[
            {
                'numeric_value': None,
                'selected': False,
                'id': 1,
                'missing': False,
                'name': 'Mujer'
            },
            # These two don't have selected yet because it is reusing the
            # API categories still, only replacing the modified one
            {
                'numeric_value': None,
                'missing': False,
                'id': 2,
                'name': 'Male'
            },
            {
                'numeric_value': None,
                'missing': True,
                'id': -1,
                'name': 'No Data'
            }
        ])
        resource.entity.refresh.assert_called_once()
        self.assertEqual(variable.categories[1].name, 'Mujer')

        # Editing Male
        variable.categories[2].edit(name='Hombre')
        resource.entity._edit.assert_called_with(categories=[
            {
                'numeric_value': None,
                'selected': False,
                'id': 1,
                'missing': False,
                'name': 'Mujer'
            },
            {
                'numeric_value': None,
                'selected': False,
                'missing': False,
                'id': 2,
                'name': 'Hombre'
            },
            # Same as above, reusing the existing value from API still
            {
                'numeric_value': None,
                'missing': True,
                'id': -1,
                'name': 'No Data'
            }
        ])

        # Try to change the ID
        with self.assertRaises(AttributeError) as err:
            variable.categories[2].edit(id=100)
        self.assertEqual(str(err.exception),
                         'Cannot edit the following attributes: id')

        # Nothing changed
        self.assertEqual(set(variable.categories.keys()), {1, 2, -1})