示例#1
0
def test_set_lazy_resolution(logger_mock):
    """ Test if `@configurable` can resolve it's configuration lazily.
    Also, test if `get_config` only lazily returns the configuration.

    This test combines multiple tests because Python does not support unloading a module:
    https://stackoverflow.com/questions/8781257/remove-an-imported-python-module

    TODO: This doesn't set `set_lazy_resolution(False)` which forces a resolution for any unresolved
    modules. In order to add more tests like so, we'd need to create more modules.
    """
    set_lazy_resolution(True)

    expected = ''
    add_config({'_tests.other_module.configured': HParams(arg=expected)})

    assert {} == get_config()
    assert logger_mock.warning.call_count == 1
    assert len(_get_skip_resolution()) == 1
    logger_mock.reset_mock()

    # NOTE: Test multiple similar config calls
    add_config({'_tests.other_module.configured': HParams(arg=expected)})
    assert len(_get_skip_resolution()) == 1

    from _tests.other_module import configured
    assert configured() == expected
    assert len(get_config()) == 1
    assert logger_mock.warning.call_count == 0
    assert len(_get_skip_resolution()) == 0
示例#2
0
def test_configurable__benchmark():
    """ Test if `@configurable` is within the ballpark of a native decorator in performance. """
    def baseline(function):
        @wraps(function)
        def decorator(*args, **kwargs):
            return function(*args, **kwargs)

        return decorator

    lambda_ = lambda arg: arg
    other_lambda_ = lambda arg: arg
    native = baseline(lambda_)
    configured = configurable(other_lambda_)

    add_config({configured: HParams(arg='')})

    samples = 10000

    # NOTE: The timer decisions are inspired by the native `timeit` module.
    gc.disable()
    iterator = itertools.repeat(None, samples)
    start = time.perf_counter()
    for _ in iterator:
        native('')
    native_elapsed = time.perf_counter() - start

    iterator = itertools.repeat(None, samples)
    start = time.perf_counter()
    for _ in iterator:
        configured()
    configured_elapsed = time.perf_counter() - start
    gc.enable()

    assert (configured_elapsed / samples) - (native_elapsed / samples) < 3e-05
示例#3
0
def test_configurable__unwrap():
    """ Test if `@configurable` works with the original `configured` path. """
    @configurable()
    def configured(arg):
        return arg

    expected = ''
    add_config({configured.__wrapped__: HParams(arg=expected)})
    assert configured() == expected
示例#4
0
def test_configurable__double_invoke():
    """ Test if `@configurable` can be called with no arguments. """
    @configurable()
    def configured(arg):
        return arg

    expected = ''
    add_config({configured: HParams(arg=expected)})
    assert configured() == expected
示例#5
0
def test__configurable__regression():
    """ Test if `@configurable` fails with a none-overridden `__init__` function for a global class.

    TODO: Support this use case. Curiously, this works for none-global classes though.
    """

    _test__resolve_configuration__super_class.__init__ = configurable(
        _test__resolve_configuration__super_class.__init__)

    with pytest.raises(TypeError):
        add_config({_test__resolve_configuration__super_class.__init__: HParams()})
示例#6
0
def test__configurable__regression(warnings_mock):
    """ Test if `@configurable` fails with a none-overridden `__init__` function for a global class.

    TODO: Support this use case. Curiously, this works for none-global classes though.
    """

    _test__resolve_configuration__super_class.__init__ = configurable(
        _test__resolve_configuration__super_class.__init__)

    add_config({_test__resolve_configuration__super_class.__init__: HParams()})
    assert warnings_mock.warn.call_count == 1
示例#7
0
def test_configurable__get_partial():
    """ Test if `@configurable#get_configured_partial` is able to export a partial with expected
    configuration.
    """
    @configurable
    def configured(arg):
        return arg

    expected = ''
    add_config({configured: HParams(arg=expected)})
    partial = configured.get_configured_partial()
    assert expected == partial()
示例#8
0
def test_configurable__empty_configuration_warnings(logger_mock):
    """ Test if `@configurable` throws warnings for an empty configuration.
    """
    @configurable
    def configured():
        pass

    add_config({configured: HParams()})

    logger_mock.reset_mock()
    configured()
    assert logger_mock.warning.call_count == 0
示例#9
0
def test_config_operators():
    """ Test the `log_config`, `clear_config`, `add_config` and `get_config` together. It's
    difficult to test them alone.
    """
    @configurable
    def configured(arg):
        pass

    assert len(get_config()) == 0
    add_config({configured: HParams()})
    log_config()  # Smoke test
    assert len(get_config()) == 1
    clear_config()
    assert len(get_config()) == 0
示例#10
0
def test_configurable__exposed_function(logger_mock, warnings_mock):
    """ Test if `@configurable` throws warnings if a configured function is run without its
    decorator.
    """
    @configurable
    def configured():
        pass

    add_config({configured: HParams()})

    logger_mock.reset_mock()
    warnings_mock.reset_mock()
    configured.__wrapped__()
    assert logger_mock.warning.call_count == 0
    assert warnings_mock.warn.call_count == 1
示例#11
0
def test_configurable__override_with_kwarg(logger_mock, warnings_mock):
    """ Test if `@configurable` throws an error on a override of an `HParam` argument that's not
    configured.
    """
    @configurable
    def configured(arg=HParam()):
        return arg

    add_config({configured: HParams()})

    logger_mock.reset_mock()
    warnings_mock.reset_mock()
    configured(arg='a')
    assert logger_mock.warning.call_count == 0
    assert warnings_mock.warn.call_count == 1
示例#12
0
def test_configurable__override(logger_mock):
    """ Test if `@configurable` throws an error on a override of an `HParam` argument that's not
    configured.
    """
    @configurable
    def configured(arg=HParam()):
        return arg

    add_config({configured: HParams()})

    logger_mock.reset_mock()
    configured('a')
    assert logger_mock.warning.call_count == 1

    # It shouldn't throw a second warning
    configured('a')
    assert logger_mock.warning.call_count == 1
示例#13
0
def test_merge_configs():
    """ Test the merging of two configurations via `add_config`.
    """

    @configurable
    def configured(arg, arg_two):
        pass

    @configurable
    def other_configured(arg):
        pass

    clear_config()
    add_config({configured: HParams(arg='arg', arg_two='arg_two')})
    add_config({other_configured: HParams()})
    assert len(get_config()) == 2
    assert get_config()[_get_function_signature(configured.__wrapped__)]['arg'] == 'arg'
    add_config({configured: HParams(arg='gra')})
    assert len(get_config()) == 2
    assert get_config()[_get_function_signature(configured.__wrapped__)]['arg'] == 'gra'
    assert get_config()[_get_function_signature(configured.__wrapped__)]['arg_two'] == 'arg_two'
    clear_config()
示例#14
0
def test_add_config__empty():
    """ Test if `add_config` works with an empty config. """
    clear_config()
    add_config({})
    assert {} == get_config()
示例#15
0
def test_configurable__regression_overriding(logger_mock, warnings_mock):
    """ Test `@configurable` that there are no warnings with a valid config. """
    add_config({_test_configurable__valid_config: HParams(hparam='')})
    _test_configurable__valid_config('arg', kwarg='')
    assert logger_mock.warning.call_count == 0
    assert warnings_mock.warn.call_count == 0