def test__get_tunable_no_conditionals(self):
        """If there are no conditionals, tunables are returned unmodified."""

        # setup
        init_params = {
            'an_init_param': 'a_value'
        }
        hyperparameters = {
            'tunable': {
                'this_is_not_conditional': {
                    'type': 'int',
                    'default': 1,
                    'range': [1, 10]
                }
            }
        }

        # run
        tunable = MLBlock._get_tunable(hyperparameters, init_params)

        # assert
        expected = {
            'this_is_not_conditional': {
                'type': 'int',
                'default': 1,
                'range': [1, 10]
            }
        }
        assert tunable == expected
    def test__get_tunable_no_condition(self):
        """If there is a conditional but no condition, the default is used."""

        # setup
        init_params = {
            'an_init_param': 'a_value'
        }
        hyperparameters = {
            'tunable': {
                'this_is_not_conditional': {
                    'type': 'int',
                    'default': 1,
                    'range': [1, 10]
                },
                'this_is_conditional': {
                    'type': 'conditional',
                    'condition': 'a_condition',
                    'default': {
                        'type': 'float',
                        'default': 0.1,
                        'values': [0, 1]
                    },
                    'values': {
                        'not_a_match': {
                            'type': 'str',
                            'default': 'a',
                            'values': ['a', 'b']
                        },
                        'neither_a_match': {
                            'type': 'int',
                            'default': 0,
                            'range': [1, 10]
                        }
                    }
                }
            }
        }

        # run
        tunable = MLBlock._get_tunable(hyperparameters, init_params)

        # assert
        expected = {
            'this_is_not_conditional': {
                'type': 'int',
                'default': 1,
                'range': [1, 10]
            },
            'this_is_conditional': {
                'type': 'float',
                'default': 0.1,
                'values': [0, 1]
            }
        }
        assert tunable == expected
    def test__get_tunable_condition_match(self):
        """If there is a conditional and it matches, only that part is returned."""

        # setup
        init_params = {
            'a_condition': 'a_match'
        }
        hyperparameters = {
            'tunable': {
                'this_is_not_conditional': {
                    'type': 'int',
                    'default': 1,
                    'range': [1, 10]
                },
                'this_is_conditional': {
                    'type': 'conditional',
                    'condition': 'a_condition',
                    'default': {
                        'type': 'float',
                        'default': 0.1,
                        'values': [0, 1]
                    },
                    'values': {
                        'not_a_match': {
                            'type': 'str',
                            'default': 'a',
                            'values': ['a', 'b']
                        },
                        'a_match': {
                            'type': 'int',
                            'default': 0,
                            'range': [1, 10]
                        }
                    }
                }
            }
        }

        # run
        tunable = MLBlock._get_tunable(hyperparameters, init_params)

        # assert
        expected = {
            'this_is_not_conditional': {
                'type': 'int',
                'default': 1,
                'range': [1, 10]
            },
            'this_is_conditional': {
                'type': 'int',
                'default': 0,
                'range': [1, 10]
            }
        }
        assert tunable == expected
    def test__get_tunable_condition_match_null(self):
        """If there is a match and it is null (None), this param is not included.

        This stands even if the default is not null.
        """

        # setup
        init_params = {
            'a_condition': 'a_match'
        }
        hyperparameters = {
            'tunable': {
                'this_is_not_conditional': {
                    'type': 'int',
                    'default': 1,
                    'range': [1, 10]
                },
                'this_is_conditional': {
                    'type': 'conditional',
                    'condition': 'a_condition',
                    'default': {
                        'type': 'float',
                        'default': 0.1,
                        'values': [0, 1]
                    },
                    'values': {
                        'not_a_match': {
                            'type': 'str',
                            'default': 'a',
                            'values': ['a', 'b']
                        },
                        'a_match': None
                    }
                }
            }
        }

        # run
        tunable = MLBlock._get_tunable(hyperparameters, init_params)

        # assert
        expected = {
            'this_is_not_conditional': {
                'type': 'int',
                'default': 1,
                'range': [1, 10]
            }
        }
        assert tunable == expected
    def test__get_tunable_condition_default_null(self):
        """If there is no match and default is null (None), this param is not included."""

        # setup
        init_params = {
            'a_condition': 'not_a_match'
        }
        hyperparameters = {
            'tunable': {
                'this_is_not_conditional': {
                    'type': 'int',
                    'default': 1,
                    'range': [1, 10]
                },
                'this_is_conditional': {
                    'type': 'conditional',
                    'condition': 'a_condition',
                    'default': None,
                    'values': {
                        'also_not_a_match': {
                            'type': 'str',
                            'default': 'a',
                            'values': ['a', 'b']
                        },
                        'neither_a_match': {
                            'type': 'int',
                            'default': 0,
                            'range': [1, 10]
                        }
                    }
                }
            }
        }

        # run
        tunable = MLBlock._get_tunable(hyperparameters, init_params)

        # assert
        expected = {
            'this_is_not_conditional': {
                'type': 'int',
                'default': 1,
                'range': [1, 10]
            }
        }
        assert tunable == expected