def test_variable_arglengths(): pop = quickstart('foo', df=pandas.DataFrame({'a': [11, 22]}), session_capture_name='test_population.py') spec = pm.compile_argspec_transforms(hasvarargs, {'population_name': 0}) assert ['_u'] == spec['required_names'] assert 2 == len(spec['required_transformers']) assert ['pop'] == spec['optional_names'] assert 1 == len(spec['optional_transformers']) xfm = spec['optional_transformers']['pop'] assert None == xfm(pop, {}) assert 7 == xfm(pop, {'pop': 7}) assert None == xfm(pop, {'zip': 7}) assert 'args' == spec['varargs'] assert None == spec['varkw'] assert ('foo', 1, 3) == pop.hasvarargs("U", 1, 2, 3, 4) assert ('foo', 'pip', 3) == pop.hasvarkw("U", pop='pip', a=1, b=2, c=3) assert ('foo', None, 0, 0) == pop.hasboth_arg('U', 'V') assert ('foo', 'W', 1, 2) == pop.hasboth_arg("U", "V", "W", "X", y="Y", z="Z") assert ('foo', 'foo', 0, 0) == pop.hasboth_argkwarg('U', 'V') assert ('foo', 'W', 1, 2) == pop.hasboth_argkwarg("U", "V", "W", "X", y="Y", z="Z") assert ('foo', 'fizz', 0, 0) == pop.hasboth_haspop('U', 'V') with pytest.raises(TypeError) as exc: pop.hasvarargs("U", 1, 2, 3, 4, pop='pip') assert "multiple values for keyword argument 'pop'" in str(exc.value) with pytest.raises(TypeError): pop.hasvarargs("U", 1, 2, a=1, b=2) with pytest.raises(TypeError): pop.hasvarkw("U", 1, 2, 3, 4, 5, 6, 7) with pytest.raises(TypeError): pop.hasboth_arg() with pytest.raises(TypeError): pop.hasboth_argkwarg() # Can only fill named parameters with population-implicit values. with pytest.raises(IndexError): @pm.population_method(population_name='0') def cannot_fill_unnamed_kwargs(*args, **kwargs): pass with pytest.raises(IndexError): @pm.population_method(population_name='pop') def cannot_fill_unnamed_args(*args, **kwargs): pass
def prepare(): if testvars['dataset'] is None: (df, csv_data) = test_plot_utils.dataset(40) tempd = tempfile.mkdtemp(prefix="bdbcontrib-test-population") csv_path = os.path.join(tempd, "data.csv") with open(csv_path, "w") as csv_f: csv_f.write(csv_data.getvalue()) bdb_path = os.path.join(tempd, "data.bdb") name = ''.join(random.choice(ascii_lowercase) for _ in range(32)) dts = quickstart(name=name, csv_path=csv_path, bdb_path=bdb_path, logger=CaptureLogger( verbose=pytest.config.option.verbose), session_capture_name="test_population.py") ensure_timeout(10, lambda: dts.analyze(models=10, iterations=20)) testvars['dataset'] = dts testvars['input_df'] = df yield testvars['dataset'], testvars['input_df']
def test_method_calls(): pop = quickstart('foo', df=pandas.DataFrame({'a': [11, 22]}), session_capture_name='test_population.py') assert 42 == pop.minimal_population_method() # It's ok to name or not name your positional args. # (But it's a syntax error to have a positional arg after a named one.) assert '12foo_cc', pop.example_population_method( df1='select * limit 1', df2=pandas.DataFrame({'b': [23, 34]})) assert '12foo_cc', pop.example_population_method( 'select * limit 1', df2=pandas.DataFrame({'b': [23, 34]})) assert '12foo_cc', pop.example_population_method( 'select * limit 1', pandas.DataFrame({'b': [23, 34]})) # It's okay to name them and get them in the wrong order too. assert '12foo_cc', pop.example_population_method( df2=pandas.DataFrame({'b': [23, 34]}), df1='select * limit 1') # The bdb argument should be present and explained in the function, and # should be absent in the method, where it's implicit. as_method = pop.example_population_method.__doc__ as_function = example_population_method.__doc__ assert not re.search(r'bdb', as_method), as_method assert re.search('bdb', as_function), as_function with pytest.raises(TypeError) as exc: pop.minimal_population_method(3) assert ('test_population_method.minimal_population_method()' ' takes no arguments (1 given)' == str(exc.value)), repr(exc) epm="test_population_method.example_population_method()" with pytest.raises(TypeError) as exc: pop.example_population_method([5]) assert (epm + " takes at least 2 arguments (1 given)" == str(exc.value)), repr(exc) with pytest.raises(TypeError) as exc: pop.example_population_method([5], gen=True) # This message is among Python's uglier warts, but I want to be consistent. assert (epm + " takes at least 2 arguments (2 given)" == str(exc.value)), repr(exc) with pytest.raises(TypeError) as exc: pop.example_population_method([1], [2], [3], [4]) assert (epm + " takes at most 3 arguments (4 given)" == str(exc.value)), repr(exc) with pytest.raises(TypeError) as exc: pop.example_population_method("SELECT * FROM %t", "SELECT * FROM %g", b="bang") assert (epm + " got an unexpected keyword argument 'b'" == str(exc.value)), repr(exc) with pytest.raises(TypeError) as exc: pop.example_population_method( "SELECT * FROM %t", df1="SELECT * FROM %g") # This is another misleading message, because the only way for it to happen # is with a required positional argument that happens to be named at the # call site. A caller might, in this case, expect keywords to be interpreted # first, for example, and positional arguments consumed in order thereafter. # Not to say that that would be a better choice. I would simply prefer "for # 2nd argument df1" rather than "for keyword argument df1". # Again, I find it more important to be consistent than to be right. assert (epm + " got multiple values for keyword argument 'df1'" == str(exc.value)), repr(exc)