feat: new alternate syntax and switch to black + isort (yeah, maybe not the best time, but that is done).
This commit is contained in:
@ -6,20 +6,14 @@ from bonobo.util.testing import all_runners
|
||||
def test_entrypoint():
|
||||
commands = {}
|
||||
|
||||
for command in pkg_resources.iter_entry_points('bonobo.commands'):
|
||||
for command in pkg_resources.iter_entry_points("bonobo.commands"):
|
||||
commands[command.name] = command
|
||||
|
||||
assert not {
|
||||
'convert',
|
||||
'init',
|
||||
'inspect',
|
||||
'run',
|
||||
'version',
|
||||
}.difference(set(commands))
|
||||
assert not {"convert", "init", "inspect", "run", "version"}.difference(set(commands))
|
||||
|
||||
|
||||
@all_runners
|
||||
def test_no_command(runner):
|
||||
_, err, exc = runner(catch_errors=True)
|
||||
assert type(exc) == SystemExit
|
||||
assert 'error: the following arguments are required: command' in err
|
||||
assert "error: the following arguments are required: command" in err
|
||||
|
||||
@ -8,10 +8,10 @@ from bonobo.util.testing import all_runners
|
||||
|
||||
@all_runners
|
||||
def test_convert(runner, tmpdir):
|
||||
csv_content = 'id;name\n1;Romain'
|
||||
tmpdir.join('in.csv').write(csv_content)
|
||||
csv_content = "id;name\n1;Romain"
|
||||
tmpdir.join("in.csv").write(csv_content)
|
||||
|
||||
with change_working_directory(tmpdir):
|
||||
runner('convert', 'in.csv', 'out.csv')
|
||||
runner("convert", "in.csv", "out.csv")
|
||||
|
||||
assert tmpdir.join('out.csv').read().strip() == csv_content
|
||||
assert tmpdir.join("out.csv").read().strip() == csv_content
|
||||
|
||||
@ -9,7 +9,7 @@ from bonobo.util.testing import all_runners
|
||||
|
||||
@all_runners
|
||||
def test_download_works_for_examples(runner):
|
||||
expected_bytes = b'hello world'
|
||||
expected_bytes = b"hello world"
|
||||
|
||||
class MockResponse(object):
|
||||
def __init__(self):
|
||||
@ -27,12 +27,13 @@ def test_download_works_for_examples(runner):
|
||||
fout = io.BytesIO()
|
||||
fout.close = lambda: None
|
||||
|
||||
with patch('bonobo.commands.download._open_url') as mock_open_url, \
|
||||
patch('bonobo.commands.download.open') as mock_open:
|
||||
with patch("bonobo.commands.download._open_url") as mock_open_url, patch(
|
||||
"bonobo.commands.download.open"
|
||||
) as mock_open:
|
||||
mock_open_url.return_value = MockResponse()
|
||||
mock_open.return_value = fout
|
||||
runner('download', 'examples/datasets/coffeeshops.txt')
|
||||
expected_url = EXAMPLES_BASE_URL + 'datasets/coffeeshops.txt'
|
||||
runner("download", "examples/datasets/coffeeshops.txt")
|
||||
expected_url = EXAMPLES_BASE_URL + "datasets/coffeeshops.txt"
|
||||
mock_open_url.assert_called_once_with(expected_url)
|
||||
|
||||
assert fout.getvalue() == expected_bytes
|
||||
@ -41,4 +42,4 @@ def test_download_works_for_examples(runner):
|
||||
@all_runners
|
||||
def test_download_fails_non_example(runner):
|
||||
with pytest.raises(ValueError):
|
||||
runner('download', 'something/entirely/different.txt')
|
||||
runner("download", "something/entirely/different.txt")
|
||||
|
||||
@ -8,22 +8,22 @@ from bonobo.util.testing import all_runners
|
||||
|
||||
@all_runners
|
||||
def test_init_file(runner, tmpdir):
|
||||
target = tmpdir.join('foo.py')
|
||||
target = tmpdir.join("foo.py")
|
||||
target_filename = str(target)
|
||||
runner('init', target_filename)
|
||||
runner("init", target_filename)
|
||||
assert os.path.exists(target_filename)
|
||||
|
||||
out, err = runner('run', target_filename)
|
||||
assert out.replace('\n', ' ').strip() == 'Hello World'
|
||||
out, err = runner("run", target_filename)
|
||||
assert out.replace("\n", " ").strip() == "Hello World"
|
||||
assert not err
|
||||
|
||||
|
||||
@all_runners
|
||||
@pytest.mark.parametrize('template', InitCommand.TEMPLATES)
|
||||
@pytest.mark.parametrize("template", InitCommand.TEMPLATES)
|
||||
def test_init_file_templates(runner, template, tmpdir):
|
||||
target = tmpdir.join('foo.py')
|
||||
target = tmpdir.join("foo.py")
|
||||
target_filename = str(target)
|
||||
runner('init', target_filename)
|
||||
runner("init", target_filename)
|
||||
assert os.path.exists(target_filename)
|
||||
out, err = runner('run', target_filename)
|
||||
out, err = runner("run", target_filename)
|
||||
assert not err
|
||||
|
||||
@ -7,42 +7,42 @@ from bonobo.util.testing import all_runners
|
||||
|
||||
@all_runners
|
||||
def test_run(runner):
|
||||
out, err = runner('run', '--quiet', get_examples_path('types/strings.py'))
|
||||
out = out.split('\n')
|
||||
assert out[0].startswith('Foo ')
|
||||
assert out[1].startswith('Bar ')
|
||||
assert out[2].startswith('Baz ')
|
||||
out, err = runner("run", "--quiet", get_examples_path("types/strings.py"))
|
||||
out = out.split("\n")
|
||||
assert out[0].startswith("Foo ")
|
||||
assert out[1].startswith("Bar ")
|
||||
assert out[2].startswith("Baz ")
|
||||
|
||||
|
||||
@all_runners
|
||||
def test_run_module(runner):
|
||||
out, err = runner('run', '--quiet', '-m', 'bonobo.examples.types.strings')
|
||||
out = out.split('\n')
|
||||
assert out[0].startswith('Foo ')
|
||||
assert out[1].startswith('Bar ')
|
||||
assert out[2].startswith('Baz ')
|
||||
out, err = runner("run", "--quiet", "-m", "bonobo.examples.types.strings")
|
||||
out = out.split("\n")
|
||||
assert out[0].startswith("Foo ")
|
||||
assert out[1].startswith("Bar ")
|
||||
assert out[2].startswith("Baz ")
|
||||
|
||||
|
||||
@all_runners
|
||||
def test_run_path(runner):
|
||||
out, err = runner('run', '--quiet', get_examples_path('types'))
|
||||
out = out.split('\n')
|
||||
assert out[0].startswith('Foo ')
|
||||
assert out[1].startswith('Bar ')
|
||||
assert out[2].startswith('Baz ')
|
||||
out, err = runner("run", "--quiet", get_examples_path("types"))
|
||||
out = out.split("\n")
|
||||
assert out[0].startswith("Foo ")
|
||||
assert out[1].startswith("Bar ")
|
||||
assert out[2].startswith("Baz ")
|
||||
|
||||
|
||||
@all_runners
|
||||
def test_install_requirements_for_dir(runner):
|
||||
dirname = get_examples_path('types')
|
||||
with patch('bonobo.commands.run._install_requirements') as install_mock:
|
||||
runner('run', '--install', dirname)
|
||||
install_mock.assert_called_once_with(os.path.join(dirname, 'requirements.txt'))
|
||||
dirname = get_examples_path("types")
|
||||
with patch("bonobo.commands.run._install_requirements") as install_mock:
|
||||
runner("run", "--install", dirname)
|
||||
install_mock.assert_called_once_with(os.path.join(dirname, "requirements.txt"))
|
||||
|
||||
|
||||
@all_runners
|
||||
def test_install_requirements_for_file(runner):
|
||||
dirname = get_examples_path('types')
|
||||
with patch('bonobo.commands.run._install_requirements') as install_mock:
|
||||
runner('run', '--install', os.path.join(dirname, 'strings.py'))
|
||||
install_mock.assert_called_once_with(os.path.join(dirname, 'requirements.txt'))
|
||||
dirname = get_examples_path("types")
|
||||
with patch("bonobo.commands.run._install_requirements") as install_mock:
|
||||
runner("run", "--install", os.path.join(dirname, "strings.py"))
|
||||
install_mock.assert_called_once_with(os.path.join(dirname, "requirements.txt"))
|
||||
|
||||
@ -5,103 +5,104 @@ from bonobo.util.testing import EnvironmentTestCase
|
||||
|
||||
@pytest.fixture
|
||||
def env1(tmpdir):
|
||||
env_file = tmpdir.join('.env_one')
|
||||
env_file.write('\n'.join((
|
||||
'SECRET=unknown',
|
||||
'PASSWORD=sweet',
|
||||
'PATH=first',
|
||||
)))
|
||||
env_file = tmpdir.join(".env_one")
|
||||
env_file.write("\n".join(("SECRET=unknown", "PASSWORD=sweet", "PATH=first")))
|
||||
return str(env_file)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def env2(tmpdir):
|
||||
env_file = tmpdir.join('.env_two')
|
||||
env_file.write('\n'.join((
|
||||
'PASSWORD=bitter',
|
||||
"PATH='second'",
|
||||
)))
|
||||
env_file = tmpdir.join(".env_two")
|
||||
env_file.write("\n".join(("PASSWORD=bitter", "PATH='second'")))
|
||||
return str(env_file)
|
||||
|
||||
|
||||
class TestDefaultEnvFile(EnvironmentTestCase):
|
||||
def test_run_with_default_env_file(self, runner, target, env1):
|
||||
env = self.run_environ(runner, *target, '--default-env-file', env1)
|
||||
assert env.get('SECRET') == 'unknown'
|
||||
assert env.get('PASSWORD') == 'sweet'
|
||||
assert env.get('PATH') == '/usr/bin'
|
||||
env = self.run_environ(runner, *target, "--default-env-file", env1)
|
||||
assert env.get("SECRET") == "unknown"
|
||||
assert env.get("PASSWORD") == "sweet"
|
||||
assert env.get("PATH") == "/usr/bin"
|
||||
|
||||
def test_run_with_multiple_default_env_files(self, runner, target, env1, env2):
|
||||
env = self.run_environ(runner, *target, '--default-env-file', env1, '--default-env-file', env2)
|
||||
assert env.get('SECRET') == 'unknown'
|
||||
assert env.get('PASSWORD') == 'sweet'
|
||||
assert env.get('PATH') == '/usr/bin'
|
||||
env = self.run_environ(runner, *target, "--default-env-file", env1, "--default-env-file", env2)
|
||||
assert env.get("SECRET") == "unknown"
|
||||
assert env.get("PASSWORD") == "sweet"
|
||||
assert env.get("PATH") == "/usr/bin"
|
||||
|
||||
env = self.run_environ(runner, *target, '--default-env-file', env2, '--default-env-file', env1)
|
||||
assert env.get('SECRET') == 'unknown'
|
||||
assert env.get('PASSWORD') == 'bitter'
|
||||
assert env.get('PATH') == '/usr/bin'
|
||||
env = self.run_environ(runner, *target, "--default-env-file", env2, "--default-env-file", env1)
|
||||
assert env.get("SECRET") == "unknown"
|
||||
assert env.get("PASSWORD") == "bitter"
|
||||
assert env.get("PATH") == "/usr/bin"
|
||||
|
||||
|
||||
class TestEnvFile(EnvironmentTestCase):
|
||||
def test_run_with_file(self, runner, target, env1):
|
||||
env = self.run_environ(runner, *target, '--env-file', env1)
|
||||
assert env.get('SECRET') == 'unknown'
|
||||
assert env.get('PASSWORD') == 'sweet'
|
||||
assert env.get('PATH') == 'first'
|
||||
env = self.run_environ(runner, *target, "--env-file", env1)
|
||||
assert env.get("SECRET") == "unknown"
|
||||
assert env.get("PASSWORD") == "sweet"
|
||||
assert env.get("PATH") == "first"
|
||||
|
||||
def test_run_with_multiple_files(self, runner, target, env1, env2):
|
||||
env = self.run_environ(runner, *target, '--env-file', env1, '--env-file', env2)
|
||||
assert env.get('SECRET') == 'unknown'
|
||||
assert env.get('PASSWORD') == 'bitter'
|
||||
assert env.get('PATH') == 'second'
|
||||
env = self.run_environ(runner, *target, "--env-file", env1, "--env-file", env2)
|
||||
assert env.get("SECRET") == "unknown"
|
||||
assert env.get("PASSWORD") == "bitter"
|
||||
assert env.get("PATH") == "second"
|
||||
|
||||
env = self.run_environ(runner, *target, '--env-file', env2, '--env-file', env1)
|
||||
assert env.get('SECRET') == 'unknown'
|
||||
assert env.get('PASSWORD') == 'sweet'
|
||||
assert env.get('PATH') == 'first'
|
||||
env = self.run_environ(runner, *target, "--env-file", env2, "--env-file", env1)
|
||||
assert env.get("SECRET") == "unknown"
|
||||
assert env.get("PASSWORD") == "sweet"
|
||||
assert env.get("PATH") == "first"
|
||||
|
||||
|
||||
class TestEnvFileCombinations(EnvironmentTestCase):
|
||||
def test_run_with_both_env_files(self, runner, target, env1, env2):
|
||||
env = self.run_environ(runner, *target, '--default-env-file', env1, '--env-file', env2)
|
||||
assert env.get('SECRET') == 'unknown'
|
||||
assert env.get('PASSWORD') == 'bitter'
|
||||
assert env.get('PATH') == 'second'
|
||||
env = self.run_environ(runner, *target, "--default-env-file", env1, "--env-file", env2)
|
||||
assert env.get("SECRET") == "unknown"
|
||||
assert env.get("PASSWORD") == "bitter"
|
||||
assert env.get("PATH") == "second"
|
||||
|
||||
def test_run_with_both_env_files_then_overrides(self, runner, target, env1, env2):
|
||||
env = self.run_environ(
|
||||
runner, *target, '--default-env-file', env1, '--env-file', env2, '--env', 'PASSWORD=mine', '--env',
|
||||
'SECRET=s3cr3t'
|
||||
runner,
|
||||
*target,
|
||||
"--default-env-file",
|
||||
env1,
|
||||
"--env-file",
|
||||
env2,
|
||||
"--env",
|
||||
"PASSWORD=mine",
|
||||
"--env",
|
||||
"SECRET=s3cr3t"
|
||||
)
|
||||
assert env.get('SECRET') == 's3cr3t'
|
||||
assert env.get('PASSWORD') == 'mine'
|
||||
assert env.get('PATH') == 'second'
|
||||
assert env.get("SECRET") == "s3cr3t"
|
||||
assert env.get("PASSWORD") == "mine"
|
||||
assert env.get("PATH") == "second"
|
||||
|
||||
|
||||
class TestEnvVars(EnvironmentTestCase):
|
||||
def test_run_no_env(self, runner, target):
|
||||
env = self.run_environ(runner, *target, environ={'USER': 'romain'})
|
||||
assert env.get('USER') == 'romain'
|
||||
env = self.run_environ(runner, *target, environ={"USER": "romain"})
|
||||
assert env.get("USER") == "romain"
|
||||
|
||||
def test_run_env(self, runner, target):
|
||||
env = self.run_environ(runner, *target, '--env', 'USER=serious', environ={'USER': 'romain'})
|
||||
assert env.get('USER') == 'serious'
|
||||
env = self.run_environ(runner, *target, "--env", "USER=serious", environ={"USER": "romain"})
|
||||
assert env.get("USER") == "serious"
|
||||
|
||||
def test_run_env_mixed(self, runner, target):
|
||||
env = self.run_environ(runner, *target, '--env', 'ONE=1', '--env', 'TWO="2"', environ={'USER': 'romain'})
|
||||
assert env.get('USER') == 'romain'
|
||||
assert env.get('ONE') == '1'
|
||||
assert env.get('TWO') == '2'
|
||||
env = self.run_environ(runner, *target, "--env", "ONE=1", "--env", 'TWO="2"', environ={"USER": "romain"})
|
||||
assert env.get("USER") == "romain"
|
||||
assert env.get("ONE") == "1"
|
||||
assert env.get("TWO") == "2"
|
||||
|
||||
def test_run_default_env(self, runner, target):
|
||||
env = self.run_environ(runner, *target, '--default-env', 'USER=clown')
|
||||
assert env.get('USER') == 'clown'
|
||||
env = self.run_environ(runner, *target, "--default-env", "USER=clown")
|
||||
assert env.get("USER") == "clown"
|
||||
|
||||
env = self.run_environ(runner, *target, '--default-env', 'USER=clown', environ={'USER': 'romain'})
|
||||
assert env.get('USER') == 'romain'
|
||||
env = self.run_environ(runner, *target, "--default-env", "USER=clown", environ={"USER": "romain"})
|
||||
assert env.get("USER") == "romain"
|
||||
|
||||
env = self.run_environ(
|
||||
runner, *target, '--env', 'USER=serious', '--default-env', 'USER=clown', environ={'USER': 'romain'}
|
||||
runner, *target, "--env", "USER=serious", "--default-env", "USER=clown", environ={"USER": "romain"}
|
||||
)
|
||||
assert env.get('USER') == 'serious'
|
||||
assert env.get("USER") == "serious"
|
||||
|
||||
@ -4,17 +4,17 @@ from bonobo.util.testing import all_runners
|
||||
|
||||
@all_runners
|
||||
def test_version(runner):
|
||||
out, err = runner('version')
|
||||
out, err = runner("version")
|
||||
out = out.strip()
|
||||
assert out.startswith('bonobo ')
|
||||
assert out.startswith("bonobo ")
|
||||
assert __version__ in out
|
||||
|
||||
out, err = runner('version', '-q')
|
||||
out, err = runner("version", "-q")
|
||||
out = out.strip()
|
||||
assert out.startswith('bonobo ')
|
||||
assert out.startswith("bonobo ")
|
||||
assert __version__ in out
|
||||
|
||||
out, err = runner('version', '-qq')
|
||||
out, err = runner("version", "-qq")
|
||||
out = out.strip()
|
||||
assert not out.startswith('bonobo ')
|
||||
assert __version__ in out
|
||||
assert not out.startswith("bonobo ")
|
||||
assert __version__ in out
|
||||
|
||||
@ -11,7 +11,7 @@ class NoOptConfigurable(Configurable):
|
||||
|
||||
class MyConfigurable(Configurable):
|
||||
required_str = Option(str)
|
||||
default_str = Option(str, default='foo')
|
||||
default_str = Option(str, default="foo")
|
||||
integer = Option(int, required=False)
|
||||
|
||||
|
||||
@ -20,7 +20,7 @@ class MyHarderConfigurable(MyConfigurable):
|
||||
|
||||
|
||||
class MyBetterConfigurable(MyConfigurable):
|
||||
required_str = Option(str, required=False, default='kaboom')
|
||||
required_str = Option(str, required=False, default="kaboom")
|
||||
|
||||
|
||||
class MyConfigurableUsingPositionalOptions(MyConfigurable):
|
||||
@ -35,7 +35,7 @@ def test_missing_required_option_error():
|
||||
|
||||
with pytest.raises(TypeError) as exc:
|
||||
MyConfigurable(_final=True)
|
||||
assert exc.match('missing 1 required option:')
|
||||
assert exc.match("missing 1 required option:")
|
||||
|
||||
|
||||
def test_missing_required_options_error():
|
||||
@ -44,29 +44,29 @@ def test_missing_required_options_error():
|
||||
|
||||
with pytest.raises(TypeError) as exc:
|
||||
MyHarderConfigurable(_final=True)
|
||||
assert exc.match('missing 2 required options:')
|
||||
assert exc.match("missing 2 required options:")
|
||||
|
||||
|
||||
def test_extraneous_option_error():
|
||||
with pytest.raises(TypeError) as exc:
|
||||
MyConfigurable(required_str='foo', hello='world')
|
||||
assert exc.match('got 1 unexpected option:')
|
||||
MyConfigurable(required_str="foo", hello="world")
|
||||
assert exc.match("got 1 unexpected option:")
|
||||
|
||||
|
||||
def test_extraneous_options_error():
|
||||
with pytest.raises(TypeError) as exc:
|
||||
MyConfigurable(required_str='foo', hello='world', acme='corp')
|
||||
assert exc.match('got 2 unexpected options:')
|
||||
MyConfigurable(required_str="foo", hello="world", acme="corp")
|
||||
assert exc.match("got 2 unexpected options:")
|
||||
|
||||
|
||||
def test_defaults():
|
||||
o = MyConfigurable(required_str='hello')
|
||||
o = MyConfigurable(required_str="hello")
|
||||
|
||||
with inspect_node(o) as ni:
|
||||
assert not ni.partial
|
||||
|
||||
assert o.required_str == 'hello'
|
||||
assert o.default_str == 'foo'
|
||||
assert o.required_str == "hello"
|
||||
assert o.default_str == "foo"
|
||||
assert o.integer is None
|
||||
|
||||
|
||||
@ -76,30 +76,30 @@ def test_str_type_factory():
|
||||
with inspect_node(o) as ni:
|
||||
assert not ni.partial
|
||||
|
||||
assert o.required_str == '42'
|
||||
assert o.default_str == 'foo'
|
||||
assert o.required_str == "42"
|
||||
assert o.default_str == "foo"
|
||||
assert o.integer is None
|
||||
|
||||
|
||||
def test_int_type_factory():
|
||||
o = MyConfigurable(required_str='yo', default_str='bar', integer='42')
|
||||
o = MyConfigurable(required_str="yo", default_str="bar", integer="42")
|
||||
|
||||
with inspect_node(o) as ni:
|
||||
assert not ni.partial
|
||||
|
||||
assert o.required_str == 'yo'
|
||||
assert o.default_str == 'bar'
|
||||
assert o.required_str == "yo"
|
||||
assert o.default_str == "bar"
|
||||
assert o.integer == 42
|
||||
|
||||
|
||||
def test_bool_type_factory():
|
||||
o = MyHarderConfigurable(required_str='yes', also_required='True')
|
||||
o = MyHarderConfigurable(required_str="yes", also_required="True")
|
||||
|
||||
with inspect_node(o) as ni:
|
||||
assert not ni.partial
|
||||
|
||||
assert o.required_str == 'yes'
|
||||
assert o.default_str == 'foo'
|
||||
assert o.required_str == "yes"
|
||||
assert o.default_str == "foo"
|
||||
assert o.integer is None
|
||||
assert o.also_required is True
|
||||
|
||||
@ -110,22 +110,22 @@ def test_option_resolution_order():
|
||||
with inspect_node(o) as ni:
|
||||
assert not ni.partial
|
||||
|
||||
assert o.required_str == 'kaboom'
|
||||
assert o.default_str == 'foo'
|
||||
assert o.required_str == "kaboom"
|
||||
assert o.default_str == "foo"
|
||||
assert o.integer is None
|
||||
|
||||
|
||||
def test_option_positional():
|
||||
o = MyConfigurableUsingPositionalOptions('1', '2', '3', required_str='hello')
|
||||
o = MyConfigurableUsingPositionalOptions("1", "2", "3", required_str="hello")
|
||||
|
||||
with inspect_node(o) as ni:
|
||||
assert not ni.partial
|
||||
|
||||
assert o.first == '1'
|
||||
assert o.second == '2'
|
||||
assert o.third == '3'
|
||||
assert o.required_str == 'hello'
|
||||
assert o.default_str == 'foo'
|
||||
assert o.first == "1"
|
||||
assert o.second == "2"
|
||||
assert o.third == "3"
|
||||
assert o.required_str == "hello"
|
||||
assert o.default_str == "foo"
|
||||
assert o.integer is None
|
||||
|
||||
|
||||
|
||||
@ -50,10 +50,7 @@ def test_define_with_decorator():
|
||||
calls = []
|
||||
|
||||
def my_handler(*args, **kwargs):
|
||||
calls.append((
|
||||
args,
|
||||
kwargs,
|
||||
))
|
||||
calls.append((args, kwargs))
|
||||
|
||||
Concrete = MethodBasedConfigurable(my_handler)
|
||||
|
||||
@ -64,7 +61,7 @@ def test_define_with_decorator():
|
||||
assert ci.type == MethodBasedConfigurable
|
||||
assert ci.partial
|
||||
|
||||
t = Concrete('foo', bar='baz')
|
||||
t = Concrete("foo", bar="baz")
|
||||
|
||||
assert callable(t.handler)
|
||||
assert len(calls) == 0
|
||||
@ -75,15 +72,12 @@ def test_define_with_decorator():
|
||||
def test_late_binding_method_decoration():
|
||||
calls = []
|
||||
|
||||
@MethodBasedConfigurable(foo='foo')
|
||||
@MethodBasedConfigurable(foo="foo")
|
||||
def Concrete(*args, **kwargs):
|
||||
calls.append((
|
||||
args,
|
||||
kwargs,
|
||||
))
|
||||
calls.append((args, kwargs))
|
||||
|
||||
assert callable(Concrete.handler)
|
||||
t = Concrete(bar='baz')
|
||||
t = Concrete(bar="baz")
|
||||
|
||||
assert callable(t.handler)
|
||||
assert len(calls) == 0
|
||||
@ -95,12 +89,9 @@ def test_define_with_argument():
|
||||
calls = []
|
||||
|
||||
def concrete_handler(*args, **kwargs):
|
||||
calls.append((
|
||||
args,
|
||||
kwargs,
|
||||
))
|
||||
calls.append((args, kwargs))
|
||||
|
||||
t = MethodBasedConfigurable(concrete_handler, 'foo', bar='baz')
|
||||
t = MethodBasedConfigurable(concrete_handler, "foo", bar="baz")
|
||||
assert callable(t.handler)
|
||||
assert len(calls) == 0
|
||||
t()
|
||||
@ -112,12 +103,9 @@ def test_define_with_inheritance():
|
||||
|
||||
class Inheriting(MethodBasedConfigurable):
|
||||
def handler(self, *args, **kwargs):
|
||||
calls.append((
|
||||
args,
|
||||
kwargs,
|
||||
))
|
||||
calls.append((args, kwargs))
|
||||
|
||||
t = Inheriting('foo', bar='baz')
|
||||
t = Inheriting("foo", bar="baz")
|
||||
assert callable(t.handler)
|
||||
assert len(calls) == 0
|
||||
t()
|
||||
@ -132,13 +120,10 @@ def test_inheritance_then_decorate():
|
||||
|
||||
@Inheriting
|
||||
def Concrete(*args, **kwargs):
|
||||
calls.append((
|
||||
args,
|
||||
kwargs,
|
||||
))
|
||||
calls.append((args, kwargs))
|
||||
|
||||
assert callable(Concrete.handler)
|
||||
t = Concrete('foo', bar='baz')
|
||||
t = Concrete("foo", bar="baz")
|
||||
assert callable(t.handler)
|
||||
assert len(calls) == 0
|
||||
t()
|
||||
|
||||
@ -12,11 +12,11 @@ class Bobby(Configurable):
|
||||
|
||||
@ContextProcessor
|
||||
def think(self, context):
|
||||
yield 'different'
|
||||
yield "different"
|
||||
|
||||
def __call__(self, think, *args, **kwargs):
|
||||
self.handler('1', *args, **kwargs)
|
||||
self.handler2('2', *args, **kwargs)
|
||||
self.handler("1", *args, **kwargs)
|
||||
self.handler2("2", *args, **kwargs)
|
||||
|
||||
|
||||
def test_partial():
|
||||
@ -40,7 +40,7 @@ def test_partial():
|
||||
assert len(ci.options) == 4
|
||||
assert len(ci.processors) == 1
|
||||
assert ci.partial
|
||||
assert ci.partial[0] == (f1, )
|
||||
assert ci.partial[0] == (f1,)
|
||||
assert not len(ci.partial[1])
|
||||
|
||||
# instanciate a more complete partial instance ...
|
||||
@ -53,13 +53,10 @@ def test_partial():
|
||||
assert len(ci.options) == 4
|
||||
assert len(ci.processors) == 1
|
||||
assert ci.partial
|
||||
assert ci.partial[0] == (
|
||||
f1,
|
||||
f2,
|
||||
)
|
||||
assert ci.partial[0] == (f1, f2)
|
||||
assert not len(ci.partial[1])
|
||||
|
||||
c = C('foo')
|
||||
c = C("foo")
|
||||
|
||||
with inspect_node(c) as ci:
|
||||
assert ci.type == Bobby
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
from operator import attrgetter
|
||||
|
||||
from bonobo.config import Configurable
|
||||
from bonobo.config.processors import ContextProcessor, resolve_processors, ContextCurrifier, use_context_processor
|
||||
from bonobo.config.processors import ContextCurrifier, ContextProcessor, resolve_processors, use_context_processor
|
||||
|
||||
|
||||
class CP1(Configurable):
|
||||
@ -11,11 +11,11 @@ class CP1(Configurable):
|
||||
|
||||
@ContextProcessor
|
||||
def a(self):
|
||||
yield 'this is A'
|
||||
yield "this is A"
|
||||
|
||||
@ContextProcessor
|
||||
def b(self, a):
|
||||
yield a.upper()[:-1] + 'b'
|
||||
yield a.upper()[:-1] + "b"
|
||||
|
||||
def __call__(self, a, b):
|
||||
return a, b
|
||||
@ -46,20 +46,20 @@ class CP3(CP2):
|
||||
|
||||
|
||||
def get_all_processors_names(cls):
|
||||
return list(map(attrgetter('__name__'), resolve_processors(cls)))
|
||||
return list(map(attrgetter("__name__"), resolve_processors(cls)))
|
||||
|
||||
|
||||
def test_inheritance_and_ordering():
|
||||
assert get_all_processors_names(CP1) == ['c', 'a', 'b']
|
||||
assert get_all_processors_names(CP2) == ['c', 'a', 'b', 'f', 'e', 'd']
|
||||
assert get_all_processors_names(CP3) == ['c', 'a', 'b', 'f', 'e', 'd', 'c', 'b']
|
||||
assert get_all_processors_names(CP1) == ["c", "a", "b"]
|
||||
assert get_all_processors_names(CP2) == ["c", "a", "b", "f", "e", "d"]
|
||||
assert get_all_processors_names(CP3) == ["c", "a", "b", "f", "e", "d", "c", "b"]
|
||||
|
||||
|
||||
def test_setup_teardown():
|
||||
o = CP1()
|
||||
stack = ContextCurrifier(o)
|
||||
stack.setup()
|
||||
assert o(*stack.args) == ('this is A', 'THIS IS b')
|
||||
assert o(*stack.args) == ("this is A", "THIS IS b")
|
||||
stack.teardown()
|
||||
|
||||
|
||||
@ -71,4 +71,4 @@ def test_processors_on_func():
|
||||
def node(context):
|
||||
pass
|
||||
|
||||
assert get_all_processors_names(node) == ['cp']
|
||||
assert get_all_processors_names(node) == ["cp"]
|
||||
|
||||
@ -4,11 +4,11 @@ import time
|
||||
import pytest
|
||||
|
||||
from bonobo.config import Configurable, Container, Exclusive, Service, use
|
||||
from bonobo.config.services import validate_service_name, create_container
|
||||
from bonobo.config.services import create_container, validate_service_name
|
||||
from bonobo.util import get_name
|
||||
|
||||
|
||||
class PrinterInterface():
|
||||
class PrinterInterface:
|
||||
def print(self, *args):
|
||||
raise NotImplementedError()
|
||||
|
||||
@ -18,46 +18,43 @@ class ConcretePrinter(PrinterInterface):
|
||||
self.prefix = prefix
|
||||
|
||||
def print(self, *args):
|
||||
return ';'.join((self.prefix, *args))
|
||||
return ";".join((self.prefix, *args))
|
||||
|
||||
|
||||
SERVICES = Container(
|
||||
printer0=ConcretePrinter(prefix='0'),
|
||||
printer1=ConcretePrinter(prefix='1'),
|
||||
)
|
||||
SERVICES = Container(printer0=ConcretePrinter(prefix="0"), printer1=ConcretePrinter(prefix="1"))
|
||||
|
||||
|
||||
class MyServiceDependantConfigurable(Configurable):
|
||||
printer = Service(PrinterInterface, )
|
||||
printer = Service(PrinterInterface)
|
||||
|
||||
def __call__(self, *args, printer: PrinterInterface):
|
||||
return printer.print(*args)
|
||||
|
||||
|
||||
def test_service_name_validator():
|
||||
assert validate_service_name('foo') == 'foo'
|
||||
assert validate_service_name('foo.bar') == 'foo.bar'
|
||||
assert validate_service_name('Foo') == 'Foo'
|
||||
assert validate_service_name('Foo.Bar') == 'Foo.Bar'
|
||||
assert validate_service_name('Foo.a0') == 'Foo.a0'
|
||||
assert validate_service_name("foo") == "foo"
|
||||
assert validate_service_name("foo.bar") == "foo.bar"
|
||||
assert validate_service_name("Foo") == "Foo"
|
||||
assert validate_service_name("Foo.Bar") == "Foo.Bar"
|
||||
assert validate_service_name("Foo.a0") == "Foo.a0"
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
validate_service_name('foo.0')
|
||||
validate_service_name("foo.0")
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
validate_service_name('0.foo')
|
||||
validate_service_name("0.foo")
|
||||
|
||||
|
||||
def test_service_dependency():
|
||||
o = MyServiceDependantConfigurable(printer='printer0')
|
||||
o = MyServiceDependantConfigurable(printer="printer0")
|
||||
|
||||
assert o('foo', 'bar', printer=SERVICES.get('printer0')) == '0;foo;bar'
|
||||
assert o('bar', 'baz', printer=SERVICES.get('printer1')) == '1;bar;baz'
|
||||
assert o('foo', 'bar', **SERVICES.kwargs_for(o)) == '0;foo;bar'
|
||||
assert o("foo", "bar", printer=SERVICES.get("printer0")) == "0;foo;bar"
|
||||
assert o("bar", "baz", printer=SERVICES.get("printer1")) == "1;bar;baz"
|
||||
assert o("foo", "bar", **SERVICES.kwargs_for(o)) == "0;foo;bar"
|
||||
|
||||
|
||||
def test_service_dependency_unavailable():
|
||||
o = MyServiceDependantConfigurable(printer='printer2')
|
||||
o = MyServiceDependantConfigurable(printer="printer2")
|
||||
with pytest.raises(KeyError):
|
||||
SERVICES.kwargs_for(o)
|
||||
|
||||
@ -72,15 +69,15 @@ class VCR:
|
||||
|
||||
def test_exclusive():
|
||||
vcr = VCR()
|
||||
vcr.append('hello')
|
||||
vcr.append("hello")
|
||||
|
||||
def record(prefix, vcr=vcr):
|
||||
with Exclusive(vcr):
|
||||
for i in range(5):
|
||||
vcr.append(' '.join((prefix, str(i))))
|
||||
vcr.append(" ".join((prefix, str(i))))
|
||||
time.sleep(0.05)
|
||||
|
||||
threads = [threading.Thread(target=record, args=(str(i), )) for i in range(5)]
|
||||
threads = [threading.Thread(target=record, args=(str(i),)) for i in range(5)]
|
||||
|
||||
for thread in threads:
|
||||
thread.start()
|
||||
@ -90,8 +87,32 @@ def test_exclusive():
|
||||
thread.join()
|
||||
|
||||
assert vcr.tape == [
|
||||
'hello', '0 0', '0 1', '0 2', '0 3', '0 4', '1 0', '1 1', '1 2', '1 3', '1 4', '2 0', '2 1', '2 2', '2 3',
|
||||
'2 4', '3 0', '3 1', '3 2', '3 3', '3 4', '4 0', '4 1', '4 2', '4 3', '4 4'
|
||||
"hello",
|
||||
"0 0",
|
||||
"0 1",
|
||||
"0 2",
|
||||
"0 3",
|
||||
"0 4",
|
||||
"1 0",
|
||||
"1 1",
|
||||
"1 2",
|
||||
"1 3",
|
||||
"1 4",
|
||||
"2 0",
|
||||
"2 1",
|
||||
"2 2",
|
||||
"2 3",
|
||||
"2 4",
|
||||
"3 0",
|
||||
"3 1",
|
||||
"3 2",
|
||||
"3 3",
|
||||
"3 4",
|
||||
"4 0",
|
||||
"4 1",
|
||||
"4 2",
|
||||
"4 3",
|
||||
"4 4",
|
||||
]
|
||||
|
||||
|
||||
@ -100,28 +121,25 @@ def test_requires():
|
||||
|
||||
services = Container(output=vcr.append)
|
||||
|
||||
@use('output')
|
||||
@use("output")
|
||||
def append(out, x):
|
||||
out(x)
|
||||
|
||||
svcargs = services.kwargs_for(append)
|
||||
assert len(svcargs) == 1
|
||||
assert svcargs['output'] == vcr.append
|
||||
assert svcargs["output"] == vcr.append
|
||||
|
||||
|
||||
@pytest.mark.parametrize('services', [None, {}])
|
||||
@pytest.mark.parametrize("services", [None, {}])
|
||||
def test_create_container_empty_values(services):
|
||||
c = create_container(services)
|
||||
assert len(c) == 2
|
||||
assert 'fs' in c and get_name(c['fs']) == 'OSFS'
|
||||
assert 'http' in c and get_name(c['http']) == 'requests'
|
||||
assert "fs" in c and get_name(c["fs"]) == "OSFS"
|
||||
assert "http" in c and get_name(c["http"]) == "requests"
|
||||
|
||||
|
||||
def test_create_container_override():
|
||||
c = create_container({
|
||||
'http': 'http',
|
||||
'fs': 'fs',
|
||||
})
|
||||
c = create_container({"http": "http", "fs": "fs"})
|
||||
assert len(c) == 2
|
||||
assert 'fs' in c and c['fs'] == 'fs'
|
||||
assert 'http' in c and c['http'] == 'http'
|
||||
assert "fs" in c and c["fs"] == "fs"
|
||||
assert "http" in c and c["http"] == "http"
|
||||
|
||||
@ -5,22 +5,22 @@ from bonobo.config import use_raw_input
|
||||
from bonobo.execution.contexts import GraphExecutionContext
|
||||
from bonobo.util.bags import BagType
|
||||
|
||||
Extracted = namedtuple('Extracted', ['id', 'name', 'value'])
|
||||
ExtractedBT = BagType('ExtractedBT', ['id', 'name', 'value'])
|
||||
Extracted = namedtuple("Extracted", ["id", "name", "value"])
|
||||
ExtractedBT = BagType("ExtractedBT", ["id", "name", "value"])
|
||||
|
||||
|
||||
def extract_nt():
|
||||
yield Extracted(id=1, name='Guido', value='.py')
|
||||
yield Extracted(id=2, name='Larry', value='.pl')
|
||||
yield Extracted(id=3, name='Dennis', value='.c')
|
||||
yield Extracted(id=4, name='Yukihiro', value='.rb')
|
||||
yield Extracted(id=1, name="Guido", value=".py")
|
||||
yield Extracted(id=2, name="Larry", value=".pl")
|
||||
yield Extracted(id=3, name="Dennis", value=".c")
|
||||
yield Extracted(id=4, name="Yukihiro", value=".rb")
|
||||
|
||||
|
||||
def extract_bt():
|
||||
yield ExtractedBT(id=1, name='Guido', value='.py')
|
||||
yield ExtractedBT(id=2, name='Larry', value='.pl')
|
||||
yield ExtractedBT(id=3, name='Dennis', value='.c')
|
||||
yield ExtractedBT(id=4, name='Yukihiro', value='.rb')
|
||||
yield ExtractedBT(id=1, name="Guido", value=".py")
|
||||
yield ExtractedBT(id=2, name="Larry", value=".pl")
|
||||
yield ExtractedBT(id=3, name="Dennis", value=".c")
|
||||
yield ExtractedBT(id=4, name="Yukihiro", value=".rb")
|
||||
|
||||
|
||||
def transform_using_args(id, name, value):
|
||||
@ -53,10 +53,18 @@ def test_execution():
|
||||
with GraphExecutionContext(graph) as context:
|
||||
context.run_until_complete()
|
||||
|
||||
assert result_args == [(2, 'Guido', 'guido.py'), (4, 'Larry', 'larry.pl'), (6, 'Dennis', 'dennis.c'),
|
||||
(8, 'Yukihiro', 'yukihiro.rb')]
|
||||
assert result_args == [
|
||||
(2, "Guido", "guido.py"),
|
||||
(4, "Larry", "larry.pl"),
|
||||
(6, "Dennis", "dennis.c"),
|
||||
(8, "Yukihiro", "yukihiro.rb"),
|
||||
]
|
||||
|
||||
assert result_nt == [(1, 'GUIDO', '.py'), (2, 'LARRY', '.pl'), (3, 'DENNIS', '.c'), (4, 'YUKIHIRO', '.rb')]
|
||||
assert result_nt == [(1, "GUIDO", ".py"), (2, "LARRY", ".pl"), (3, "DENNIS", ".c"), (4, "YUKIHIRO", ".rb")]
|
||||
|
||||
assert result_bt == [(2, 'Guido', 'guido.py'), (4, 'Larry', 'larry.pl'), (6, 'Dennis', 'dennis.c'),
|
||||
(8, 'Yukihiro', 'yukihiro.rb')]
|
||||
assert result_bt == [
|
||||
(2, "Guido", "guido.py"),
|
||||
(4, "Larry", "larry.pl"),
|
||||
(6, "Dennis", "dennis.c"),
|
||||
(8, "Yukihiro", "yukihiro.rb"),
|
||||
]
|
||||
|
||||
@ -1,14 +1,14 @@
|
||||
from bonobo import Graph
|
||||
from bonobo.constants import EMPTY, BEGIN, END
|
||||
from bonobo.constants import BEGIN, EMPTY, END
|
||||
from bonobo.execution.contexts import GraphExecutionContext
|
||||
|
||||
|
||||
def raise_an_error(*args, **kwargs):
|
||||
raise Exception('Careful, man, there\'s a beverage here!')
|
||||
raise Exception("Careful, man, there's a beverage here!")
|
||||
|
||||
|
||||
def raise_an_unrecoverrable_error(*args, **kwargs):
|
||||
raise Exception('You are entering a world of pain!')
|
||||
raise Exception("You are entering a world of pain!")
|
||||
|
||||
|
||||
def test_lifecycle_of_empty_graph():
|
||||
|
||||
@ -6,131 +6,131 @@ from bonobo import Graph
|
||||
from bonobo.constants import EMPTY
|
||||
from bonobo.execution.contexts.node import NodeExecutionContext, split_token
|
||||
from bonobo.execution.strategies import NaiveStrategy
|
||||
from bonobo.util.envelopes import F_NOT_MODIFIED, F_INHERIT
|
||||
from bonobo.util.testing import BufferingNodeExecutionContext, BufferingGraphExecutionContext
|
||||
from bonobo.util.envelopes import F_INHERIT, F_NOT_MODIFIED
|
||||
from bonobo.util.testing import BufferingGraphExecutionContext, BufferingNodeExecutionContext
|
||||
|
||||
|
||||
def test_node_string():
|
||||
def f():
|
||||
return 'foo'
|
||||
return "foo"
|
||||
|
||||
with BufferingNodeExecutionContext(f) as context:
|
||||
context.write_sync(EMPTY)
|
||||
output = context.get_buffer()
|
||||
|
||||
assert len(output) == 1
|
||||
assert output[0] == ('foo', )
|
||||
assert output[0] == ("foo",)
|
||||
|
||||
def g():
|
||||
yield 'foo'
|
||||
yield 'bar'
|
||||
yield "foo"
|
||||
yield "bar"
|
||||
|
||||
with BufferingNodeExecutionContext(g) as context:
|
||||
context.write_sync(EMPTY)
|
||||
output = context.get_buffer()
|
||||
|
||||
assert len(output) == 2
|
||||
assert output[0] == ('foo', )
|
||||
assert output[1] == ('bar', )
|
||||
assert output[0] == ("foo",)
|
||||
assert output[1] == ("bar",)
|
||||
|
||||
|
||||
def test_node_bytes():
|
||||
def f():
|
||||
return b'foo'
|
||||
return b"foo"
|
||||
|
||||
with BufferingNodeExecutionContext(f) as context:
|
||||
context.write_sync(EMPTY)
|
||||
|
||||
output = context.get_buffer()
|
||||
assert len(output) == 1
|
||||
assert output[0] == (b'foo', )
|
||||
assert output[0] == (b"foo",)
|
||||
|
||||
def g():
|
||||
yield b'foo'
|
||||
yield b'bar'
|
||||
yield b"foo"
|
||||
yield b"bar"
|
||||
|
||||
with BufferingNodeExecutionContext(g) as context:
|
||||
context.write_sync(EMPTY)
|
||||
output = context.get_buffer()
|
||||
|
||||
assert len(output) == 2
|
||||
assert output[0] == (b'foo', )
|
||||
assert output[1] == (b'bar', )
|
||||
assert output[0] == (b"foo",)
|
||||
assert output[1] == (b"bar",)
|
||||
|
||||
|
||||
def test_node_dict():
|
||||
def f():
|
||||
return {'id': 1, 'name': 'foo'}
|
||||
return {"id": 1, "name": "foo"}
|
||||
|
||||
with BufferingNodeExecutionContext(f) as context:
|
||||
context.write_sync(EMPTY)
|
||||
output = context.get_buffer()
|
||||
assert len(output) == 1
|
||||
assert output[0] == ({'id': 1, 'name': 'foo'}, )
|
||||
assert output[0] == ({"id": 1, "name": "foo"},)
|
||||
|
||||
def g():
|
||||
yield {'id': 1, 'name': 'foo'}
|
||||
yield {'id': 2, 'name': 'bar'}
|
||||
yield {"id": 1, "name": "foo"}
|
||||
yield {"id": 2, "name": "bar"}
|
||||
|
||||
with BufferingNodeExecutionContext(g) as context:
|
||||
context.write_sync(EMPTY)
|
||||
output = context.get_buffer()
|
||||
assert len(output) == 2
|
||||
assert output[0] == ({'id': 1, 'name': 'foo'}, )
|
||||
assert output[1] == ({'id': 2, 'name': 'bar'}, )
|
||||
assert output[0] == ({"id": 1, "name": "foo"},)
|
||||
assert output[1] == ({"id": 2, "name": "bar"},)
|
||||
|
||||
|
||||
def test_node_dict_chained():
|
||||
strategy = NaiveStrategy(GraphExecutionContextType=BufferingGraphExecutionContext)
|
||||
|
||||
def f():
|
||||
return {'id': 1, 'name': 'foo'}
|
||||
return {"id": 1, "name": "foo"}
|
||||
|
||||
def uppercase_name(values):
|
||||
return {**values, 'name': values['name'].upper()}
|
||||
return {**values, "name": values["name"].upper()}
|
||||
|
||||
graph = Graph(f, uppercase_name)
|
||||
context = strategy.execute(graph)
|
||||
output = context.get_buffer()
|
||||
|
||||
assert len(output) == 1
|
||||
assert output[0] == ({'id': 1, 'name': 'FOO'}, )
|
||||
assert output[0] == ({"id": 1, "name": "FOO"},)
|
||||
|
||||
def g():
|
||||
yield {'id': 1, 'name': 'foo'}
|
||||
yield {'id': 2, 'name': 'bar'}
|
||||
yield {"id": 1, "name": "foo"}
|
||||
yield {"id": 2, "name": "bar"}
|
||||
|
||||
graph = Graph(g, uppercase_name)
|
||||
context = strategy.execute(graph)
|
||||
output = context.get_buffer()
|
||||
|
||||
assert len(output) == 2
|
||||
assert output[0] == ({'id': 1, 'name': 'FOO'}, )
|
||||
assert output[1] == ({'id': 2, 'name': 'BAR'}, )
|
||||
assert output[0] == ({"id": 1, "name": "FOO"},)
|
||||
assert output[1] == ({"id": 2, "name": "BAR"},)
|
||||
|
||||
|
||||
def test_node_tuple():
|
||||
def f():
|
||||
return 'foo', 'bar'
|
||||
return "foo", "bar"
|
||||
|
||||
with BufferingNodeExecutionContext(f) as context:
|
||||
context.write_sync(EMPTY)
|
||||
output = context.get_buffer()
|
||||
|
||||
assert len(output) == 1
|
||||
assert output[0] == ('foo', 'bar')
|
||||
assert output[0] == ("foo", "bar")
|
||||
|
||||
def g():
|
||||
yield 'foo', 'bar'
|
||||
yield 'foo', 'baz'
|
||||
yield "foo", "bar"
|
||||
yield "foo", "baz"
|
||||
|
||||
with BufferingNodeExecutionContext(g) as context:
|
||||
context.write_sync(EMPTY)
|
||||
output = context.get_buffer()
|
||||
|
||||
assert len(output) == 2
|
||||
assert output[0] == ('foo', 'bar')
|
||||
assert output[1] == ('foo', 'baz')
|
||||
assert output[0] == ("foo", "bar")
|
||||
assert output[1] == ("foo", "baz")
|
||||
|
||||
|
||||
def test_node_tuple_chained():
|
||||
@ -140,50 +140,50 @@ def test_node_tuple_chained():
|
||||
return tuple(map(str.upper, args))
|
||||
|
||||
def f():
|
||||
return 'foo', 'bar'
|
||||
return "foo", "bar"
|
||||
|
||||
graph = Graph(f, uppercase)
|
||||
context = strategy.execute(graph)
|
||||
output = context.get_buffer()
|
||||
|
||||
assert len(output) == 1
|
||||
assert output[0] == ('FOO', 'BAR')
|
||||
assert output[0] == ("FOO", "BAR")
|
||||
|
||||
def g():
|
||||
yield 'foo', 'bar'
|
||||
yield 'foo', 'baz'
|
||||
yield "foo", "bar"
|
||||
yield "foo", "baz"
|
||||
|
||||
graph = Graph(g, uppercase)
|
||||
context = strategy.execute(graph)
|
||||
output = context.get_buffer()
|
||||
|
||||
assert len(output) == 2
|
||||
assert output[0] == ('FOO', 'BAR')
|
||||
assert output[1] == ('FOO', 'BAZ')
|
||||
assert output[0] == ("FOO", "BAR")
|
||||
assert output[1] == ("FOO", "BAZ")
|
||||
|
||||
|
||||
def test_node_tuple_dict():
|
||||
def f():
|
||||
return 'foo', 'bar', {'id': 1}
|
||||
return "foo", "bar", {"id": 1}
|
||||
|
||||
with BufferingNodeExecutionContext(f) as context:
|
||||
context.write_sync(EMPTY)
|
||||
output = context.get_buffer()
|
||||
|
||||
assert len(output) == 1
|
||||
assert output[0] == ('foo', 'bar', {'id': 1})
|
||||
assert output[0] == ("foo", "bar", {"id": 1})
|
||||
|
||||
def g():
|
||||
yield 'foo', 'bar', {'id': 1}
|
||||
yield 'foo', 'baz', {'id': 2}
|
||||
yield "foo", "bar", {"id": 1}
|
||||
yield "foo", "baz", {"id": 2}
|
||||
|
||||
with BufferingNodeExecutionContext(g) as context:
|
||||
context.write_sync(EMPTY)
|
||||
output = context.get_buffer()
|
||||
|
||||
assert len(output) == 2
|
||||
assert output[0] == ('foo', 'bar', {'id': 1})
|
||||
assert output[1] == ('foo', 'baz', {'id': 2})
|
||||
assert output[0] == ("foo", "bar", {"id": 1})
|
||||
assert output[1] == ("foo", "baz", {"id": 2})
|
||||
|
||||
|
||||
def test_node_lifecycle_natural():
|
||||
@ -229,9 +229,9 @@ def test_node_lifecycle_with_kill():
|
||||
|
||||
def test_split_token():
|
||||
with pytest.deprecated_call():
|
||||
assert split_token(('foo', 'bar')) == (set(), ('foo', 'bar'))
|
||||
assert split_token(("foo", "bar")) == (set(), ("foo", "bar"))
|
||||
assert split_token(()) == (set(), ())
|
||||
assert split_token('') == (set(), ('', ))
|
||||
assert split_token("") == (set(), ("",))
|
||||
|
||||
|
||||
def test_split_token_duplicate():
|
||||
@ -247,17 +247,17 @@ def test_split_token_duplicate():
|
||||
def test_split_token_not_modified():
|
||||
with pytest.deprecated_call():
|
||||
with pytest.raises(ValueError):
|
||||
split_token((F_NOT_MODIFIED, 'foo', 'bar'))
|
||||
split_token((F_NOT_MODIFIED, "foo", "bar"))
|
||||
with pytest.raises(ValueError):
|
||||
split_token((F_NOT_MODIFIED, F_INHERIT))
|
||||
with pytest.raises(ValueError):
|
||||
split_token((F_INHERIT, F_NOT_MODIFIED))
|
||||
assert split_token(F_NOT_MODIFIED) == ({F_NOT_MODIFIED}, ())
|
||||
assert split_token((F_NOT_MODIFIED, )) == ({F_NOT_MODIFIED}, ())
|
||||
assert split_token((F_NOT_MODIFIED,)) == ({F_NOT_MODIFIED}, ())
|
||||
|
||||
|
||||
def test_split_token_inherit():
|
||||
with pytest.deprecated_call():
|
||||
assert split_token(F_INHERIT) == ({F_INHERIT}, ())
|
||||
assert split_token((F_INHERIT, )) == ({F_INHERIT}, ())
|
||||
assert split_token((F_INHERIT, 'foo', 'bar')) == ({F_INHERIT}, ('foo', 'bar'))
|
||||
assert split_token((F_INHERIT,)) == ({F_INHERIT}, ())
|
||||
assert split_token((F_INHERIT, "foo", "bar")) == ({F_INHERIT}, ("foo", "bar"))
|
||||
|
||||
@ -6,9 +6,9 @@ from bonobo.execution import events
|
||||
def test_names():
|
||||
# This test looks useless, but as it's becoming the pliugin API, I want to make sure that nothing changes here, or
|
||||
# notice it otherwise.
|
||||
for name in 'start', 'started', 'tick', 'stop', 'stopped', 'kill':
|
||||
for name in "start", "started", "tick", "stop", "stopped", "kill":
|
||||
event_name = getattr(events, name.upper())
|
||||
assert event_name == '.'.join(('execution', name))
|
||||
assert event_name == ".".join(("execution", name))
|
||||
|
||||
|
||||
def test_event_object():
|
||||
|
||||
@ -14,16 +14,11 @@ class ResponseMock:
|
||||
return {}
|
||||
else:
|
||||
self.count += 1
|
||||
return {
|
||||
'records': self.json_value,
|
||||
}
|
||||
return {"records": self.json_value}
|
||||
|
||||
|
||||
def test_read_from_opendatasoft_api():
|
||||
extract = OpenDataSoftAPI(dataset='test-a-set')
|
||||
with patch('requests.get', return_value=ResponseMock([
|
||||
{'fields': {'foo': 'bar'}},
|
||||
{'fields': {'foo': 'zab'}},
|
||||
])):
|
||||
for line in extract('http://example.com/', ValueHolder(0)):
|
||||
assert 'foo' in line
|
||||
extract = OpenDataSoftAPI(dataset="test-a-set")
|
||||
with patch("requests.get", return_value=ResponseMock([{"fields": {"foo": "bar"}}, {"fields": {"foo": "zab"}}])):
|
||||
for line in extract("http://example.com/", ValueHolder(0)):
|
||||
assert "foo" in line
|
||||
|
||||
@ -1,27 +1,24 @@
|
||||
from bonobo.util.envelopes import AppendingEnvelope
|
||||
from bonobo.util.testing import BufferingNodeExecutionContext
|
||||
|
||||
messages = [
|
||||
('Hello', ),
|
||||
('Goodbye', ),
|
||||
]
|
||||
messages = [("Hello",), ("Goodbye",)]
|
||||
|
||||
|
||||
def append(*args):
|
||||
return AppendingEnvelope('!')
|
||||
return AppendingEnvelope("!")
|
||||
|
||||
|
||||
def test_inherit():
|
||||
with BufferingNodeExecutionContext(append) as context:
|
||||
context.write_sync(*messages)
|
||||
|
||||
assert context.get_buffer() == list(map(lambda x: x + ('!', ), messages))
|
||||
assert context.get_buffer() == list(map(lambda x: x + ("!",), messages))
|
||||
|
||||
|
||||
def test_inherit_bag_tuple():
|
||||
with BufferingNodeExecutionContext(append) as context:
|
||||
context.set_input_fields(['message'])
|
||||
context.set_input_fields(["message"])
|
||||
context.write_sync(*messages)
|
||||
|
||||
assert context.get_output_fields() == ('message', '0')
|
||||
assert context.get_buffer() == list(map(lambda x: x + ('!', ), messages))
|
||||
assert context.get_output_fields() == ("message", "0")
|
||||
assert context.get_buffer() == list(map(lambda x: x + ("!",), messages))
|
||||
|
||||
@ -7,10 +7,7 @@ def useless(*args, **kwargs):
|
||||
|
||||
|
||||
def test_not_modified():
|
||||
input_messages = [
|
||||
('foo', 'bar'),
|
||||
('foo', 'baz'),
|
||||
]
|
||||
input_messages = [("foo", "bar"), ("foo", "baz")]
|
||||
|
||||
with BufferingNodeExecutionContext(useless) as context:
|
||||
context.write_sync(*input_messages)
|
||||
|
||||
@ -6,13 +6,14 @@ import pytest
|
||||
|
||||
from bonobo import CsvReader, CsvWriter
|
||||
from bonobo.constants import EMPTY
|
||||
from bonobo.util.testing import FilesystemTester, BufferingNodeExecutionContext, WriterTest, ConfigurableNodeTest, \
|
||||
ReaderTest
|
||||
from bonobo.util.testing import (
|
||||
BufferingNodeExecutionContext, ConfigurableNodeTest, FilesystemTester, ReaderTest, WriterTest
|
||||
)
|
||||
|
||||
csv_tester = FilesystemTester('csv')
|
||||
csv_tester.input_data = 'a,b,c\na foo,b foo,c foo\na bar,b bar,c bar'
|
||||
csv_tester = FilesystemTester("csv")
|
||||
csv_tester.input_data = "a,b,c\na foo,b foo,c foo\na bar,b bar,c bar"
|
||||
|
||||
defaults = {'lineterminator': '\n'}
|
||||
defaults = {"lineterminator": "\n"}
|
||||
|
||||
incontext = ConfigurableNodeTest.incontext
|
||||
|
||||
@ -23,15 +24,10 @@ def test_read_csv_from_file_kwargs(tmpdir):
|
||||
with BufferingNodeExecutionContext(CsvReader(filename, **defaults), services=services) as context:
|
||||
context.write_sync(EMPTY)
|
||||
|
||||
assert context.get_buffer_args_as_dicts() == [{
|
||||
'a': 'a foo',
|
||||
'b': 'b foo',
|
||||
'c': 'c foo',
|
||||
}, {
|
||||
'a': 'a bar',
|
||||
'b': 'b bar',
|
||||
'c': 'c bar',
|
||||
}]
|
||||
assert context.get_buffer_args_as_dicts() == [
|
||||
{"a": "a foo", "b": "b foo", "c": "c foo"},
|
||||
{"a": "a bar", "b": "b bar", "c": "c bar"},
|
||||
]
|
||||
|
||||
|
||||
###
|
||||
@ -40,86 +36,66 @@ def test_read_csv_from_file_kwargs(tmpdir):
|
||||
|
||||
|
||||
class Csv:
|
||||
extension = 'csv'
|
||||
extension = "csv"
|
||||
ReaderNodeType = CsvReader
|
||||
WriterNodeType = CsvWriter
|
||||
|
||||
|
||||
L1, L2, L3, L4 = ('a', 'hey'), ('b', 'bee'), ('c', 'see'), ('d', 'dee')
|
||||
LL = ('i', 'have', 'more', 'values')
|
||||
L1, L2, L3, L4 = ("a", "hey"), ("b", "bee"), ("c", "see"), ("d", "dee")
|
||||
LL = ("i", "have", "more", "values")
|
||||
|
||||
|
||||
class CsvReaderTest(Csv, ReaderTest, TestCase):
|
||||
input_data = '\n'.join((
|
||||
'id,name',
|
||||
'1,John Doe',
|
||||
'2,Jane Doe',
|
||||
',DPR',
|
||||
'42,Elon Musk',
|
||||
))
|
||||
input_data = "\n".join(("id,name", "1,John Doe", "2,Jane Doe", ",DPR", "42,Elon Musk"))
|
||||
|
||||
def check_output(self, context, *, prepend=None):
|
||||
out = context.get_buffer()
|
||||
assert out == (prepend or list()) + [
|
||||
('1', 'John Doe'),
|
||||
('2', 'Jane Doe'),
|
||||
('', 'DPR'),
|
||||
('42', 'Elon Musk'),
|
||||
]
|
||||
assert out == (prepend or list()) + [("1", "John Doe"), ("2", "Jane Doe"), ("", "DPR"), ("42", "Elon Musk")]
|
||||
|
||||
@incontext()
|
||||
def test_nofields(self, context):
|
||||
context.write_sync(EMPTY)
|
||||
context.stop()
|
||||
self.check_output(context)
|
||||
assert context.get_output_fields() == ('id', 'name')
|
||||
assert context.get_output_fields() == ("id", "name")
|
||||
|
||||
@incontext(output_type=tuple)
|
||||
def test_output_type(self, context):
|
||||
context.write_sync(EMPTY)
|
||||
context.stop()
|
||||
self.check_output(context, prepend=[('id', 'name')])
|
||||
self.check_output(context, prepend=[("id", "name")])
|
||||
|
||||
@incontext(
|
||||
output_fields=(
|
||||
'x',
|
||||
'y',
|
||||
), skip=1
|
||||
)
|
||||
@incontext(output_fields=("x", "y"), skip=1)
|
||||
def test_output_fields(self, context):
|
||||
context.write_sync(EMPTY)
|
||||
context.stop()
|
||||
self.check_output(context)
|
||||
assert context.get_output_fields() == ('x', 'y')
|
||||
assert context.get_output_fields() == ("x", "y")
|
||||
|
||||
@incontext(quoting=QUOTE_ALL)
|
||||
def test_quoting(self, context):
|
||||
context.write_sync(EMPTY)
|
||||
context.stop()
|
||||
self.check_output(context)
|
||||
assert context.get_output_fields() == ('id', 'name')
|
||||
assert context.get_output_fields() == ("id", "name")
|
||||
|
||||
|
||||
class CsvWriterTest(Csv, WriterTest, TestCase):
|
||||
@incontext()
|
||||
def test_fields(self, context):
|
||||
context.set_input_fields(['foo', 'bar'])
|
||||
context.write_sync(('a', 'b'), ('c', 'd'))
|
||||
context.set_input_fields(["foo", "bar"])
|
||||
context.write_sync(("a", "b"), ("c", "d"))
|
||||
context.stop()
|
||||
|
||||
assert self.readlines() == (
|
||||
'foo,bar',
|
||||
'a,b',
|
||||
'c,d',
|
||||
)
|
||||
assert self.readlines() == ("foo,bar", "a,b", "c,d")
|
||||
|
||||
@incontext()
|
||||
def test_fields_from_type(self, context):
|
||||
context.set_input_type(namedtuple('Point', 'x y'))
|
||||
context.set_input_type(namedtuple("Point", "x y"))
|
||||
context.write_sync((1, 2), (3, 4))
|
||||
context.stop()
|
||||
|
||||
assert self.readlines() == ('x,y', '1,2', '3,4')
|
||||
assert self.readlines() == ("x,y", "1,2", "3,4")
|
||||
|
||||
@incontext()
|
||||
def test_nofields_multiple_args(self, context):
|
||||
@ -127,30 +103,21 @@ class CsvWriterTest(Csv, WriterTest, TestCase):
|
||||
context.write_sync((L1, L2), (L3, L4))
|
||||
context.stop()
|
||||
|
||||
assert self.readlines() == (
|
||||
'a,hey',
|
||||
'b,bee',
|
||||
'c,see',
|
||||
'd,dee',
|
||||
)
|
||||
assert self.readlines() == ("a,hey", "b,bee", "c,see", "d,dee")
|
||||
|
||||
@incontext()
|
||||
def test_nofields_multiple_args_length_mismatch(self, context):
|
||||
# if length of input vary, then we get a TypeError (unrecoverable)
|
||||
with pytest.raises(TypeError):
|
||||
context.write_sync((L1, L2), (L3, ))
|
||||
context.write_sync((L1, L2), (L3,))
|
||||
|
||||
@incontext()
|
||||
def test_nofields_single_arg(self, context):
|
||||
# single args are just dumped, shapes can vary.
|
||||
context.write_sync((L1, ), (LL, ), (L3, ))
|
||||
context.write_sync((L1,), (LL,), (L3,))
|
||||
context.stop()
|
||||
|
||||
assert self.readlines() == (
|
||||
'a,hey',
|
||||
'i,have,more,values',
|
||||
'c,see',
|
||||
)
|
||||
assert self.readlines() == ("a,hey", "i,have,more,values", "c,see")
|
||||
|
||||
@incontext()
|
||||
def test_nofields_empty_args(self, context):
|
||||
|
||||
@ -5,26 +5,23 @@ from bonobo.constants import EMPTY
|
||||
from bonobo.execution.contexts.node import NodeExecutionContext
|
||||
from bonobo.util.testing import BufferingNodeExecutionContext, FilesystemTester
|
||||
|
||||
txt_tester = FilesystemTester('txt')
|
||||
txt_tester.input_data = 'Hello\nWorld\n'
|
||||
txt_tester = FilesystemTester("txt")
|
||||
txt_tester.input_data = "Hello\nWorld\n"
|
||||
|
||||
|
||||
def test_file_writer_contextless(tmpdir):
|
||||
fs, filename, services = txt_tester.get_services_for_writer(tmpdir)
|
||||
|
||||
with FileWriter(path=filename).open(fs) as fp:
|
||||
fp.write('Yosh!')
|
||||
fp.write("Yosh!")
|
||||
|
||||
with fs.open(filename) as fp:
|
||||
assert fp.read() == 'Yosh!'
|
||||
assert fp.read() == "Yosh!"
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'lines,output',
|
||||
[
|
||||
(('ACME', ), 'ACME'), # one line...
|
||||
(('Foo', 'Bar', 'Baz'), 'Foo\nBar\nBaz'), # more than one line...
|
||||
]
|
||||
"lines,output",
|
||||
[(("ACME",), "ACME"), (("Foo", "Bar", "Baz"), "Foo\nBar\nBaz")], # one line... # more than one line...
|
||||
)
|
||||
def test_file_writer_in_context(tmpdir, lines, output):
|
||||
fs, filename, services = txt_tester.get_services_for_writer(tmpdir)
|
||||
@ -44,5 +41,5 @@ def test_file_reader(tmpdir):
|
||||
|
||||
output = context.get_buffer()
|
||||
assert len(output) == 2
|
||||
assert output[0] == ('Hello', )
|
||||
assert output[1] == ('World', )
|
||||
assert output[0] == ("Hello",)
|
||||
assert output[1] == ("World",)
|
||||
|
||||
@ -4,14 +4,13 @@ from unittest import TestCase
|
||||
|
||||
import pytest
|
||||
|
||||
from bonobo import JsonReader, JsonWriter
|
||||
from bonobo import LdjsonReader, LdjsonWriter
|
||||
from bonobo import JsonReader, JsonWriter, LdjsonReader, LdjsonWriter
|
||||
from bonobo.constants import EMPTY
|
||||
from bonobo.util.testing import WriterTest, ReaderTest, ConfigurableNodeTest
|
||||
from bonobo.util.testing import ConfigurableNodeTest, ReaderTest, WriterTest
|
||||
|
||||
FOOBAR = {'foo': 'bar'}
|
||||
OD_ABC = OrderedDict((('a', 'A'), ('b', 'B'), ('c', 'C')))
|
||||
FOOBAZ = {'foo': 'baz'}
|
||||
FOOBAR = {"foo": "bar"}
|
||||
OD_ABC = OrderedDict((("a", "A"), ("b", "B"), ("c", "C")))
|
||||
FOOBAZ = {"foo": "baz"}
|
||||
|
||||
incontext = ConfigurableNodeTest.incontext
|
||||
|
||||
@ -21,7 +20,7 @@ incontext = ConfigurableNodeTest.incontext
|
||||
|
||||
|
||||
class Json:
|
||||
extension = 'json'
|
||||
extension = "json"
|
||||
ReaderNodeType = JsonReader
|
||||
WriterNodeType = JsonWriter
|
||||
|
||||
@ -34,88 +33,61 @@ class JsonReaderDictsTest(Json, ReaderTest, TestCase):
|
||||
context.write_sync(EMPTY)
|
||||
context.stop()
|
||||
|
||||
assert context.get_buffer() == [
|
||||
({
|
||||
"foo": "bar"
|
||||
}, ),
|
||||
({
|
||||
"baz": "boz"
|
||||
}, ),
|
||||
]
|
||||
assert context.get_buffer() == [({"foo": "bar"},), ({"baz": "boz"},)]
|
||||
|
||||
|
||||
class JsonReaderListsTest(Json, ReaderTest, TestCase):
|
||||
input_data = '[[1,2,3],\n[4,5,6]]'
|
||||
input_data = "[[1,2,3],\n[4,5,6]]"
|
||||
|
||||
@incontext()
|
||||
def test_nofields(self, context):
|
||||
context.write_sync(EMPTY)
|
||||
context.stop()
|
||||
|
||||
assert context.get_buffer() == [
|
||||
([1, 2, 3], ),
|
||||
([4, 5, 6], ),
|
||||
]
|
||||
assert context.get_buffer() == [([1, 2, 3],), ([4, 5, 6],)]
|
||||
|
||||
@incontext(output_type=tuple)
|
||||
def test_output_type(self, context):
|
||||
context.write_sync(EMPTY)
|
||||
context.stop()
|
||||
|
||||
assert context.get_buffer() == [
|
||||
([1, 2, 3], ),
|
||||
([4, 5, 6], ),
|
||||
]
|
||||
assert context.get_buffer() == [([1, 2, 3],), ([4, 5, 6],)]
|
||||
|
||||
|
||||
class JsonReaderStringsTest(Json, ReaderTest, TestCase):
|
||||
input_data = '[' + ',\n'.join(map(json.dumps, ('foo', 'bar', 'baz'))) + ']'
|
||||
input_data = "[" + ",\n".join(map(json.dumps, ("foo", "bar", "baz"))) + "]"
|
||||
|
||||
@incontext()
|
||||
def test_nofields(self, context):
|
||||
context.write_sync(EMPTY)
|
||||
context.stop()
|
||||
|
||||
assert context.get_buffer() == [
|
||||
('foo', ),
|
||||
('bar', ),
|
||||
('baz', ),
|
||||
]
|
||||
assert context.get_buffer() == [("foo",), ("bar",), ("baz",)]
|
||||
|
||||
@incontext(output_type=tuple)
|
||||
def test_output_type(self, context):
|
||||
context.write_sync(EMPTY)
|
||||
context.stop()
|
||||
|
||||
assert context.get_buffer() == [
|
||||
('foo', ),
|
||||
('bar', ),
|
||||
('baz', ),
|
||||
]
|
||||
assert context.get_buffer() == [("foo",), ("bar",), ("baz",)]
|
||||
|
||||
|
||||
class JsonWriterTest(Json, WriterTest, TestCase):
|
||||
@incontext()
|
||||
def test_fields(self, context):
|
||||
context.set_input_fields(['foo', 'bar'])
|
||||
context.write_sync(('a', 'b'), ('c', 'd'))
|
||||
context.set_input_fields(["foo", "bar"])
|
||||
context.write_sync(("a", "b"), ("c", "d"))
|
||||
context.stop()
|
||||
|
||||
assert self.readlines() == (
|
||||
'[{"foo": "a", "bar": "b"},',
|
||||
'{"foo": "c", "bar": "d"}]',
|
||||
)
|
||||
assert self.readlines() == ('[{"foo": "a", "bar": "b"},', '{"foo": "c", "bar": "d"}]')
|
||||
|
||||
@incontext()
|
||||
def test_fields_from_type(self, context):
|
||||
context.set_input_type(namedtuple('Point', 'x y'))
|
||||
context.set_input_type(namedtuple("Point", "x y"))
|
||||
context.write_sync((1, 2), (3, 4))
|
||||
context.stop()
|
||||
|
||||
assert self.readlines() == (
|
||||
'[{"x": 1, "y": 2},',
|
||||
'{"x": 3, "y": 4}]',
|
||||
)
|
||||
assert self.readlines() == ('[{"x": 1, "y": 2},', '{"x": 3, "y": 4}]')
|
||||
|
||||
@incontext()
|
||||
def test_nofields_multiple_args(self, context):
|
||||
@ -144,11 +116,7 @@ class JsonWriterTest(Json, WriterTest, TestCase):
|
||||
context.write_sync(FOOBAR, OD_ABC, FOOBAZ)
|
||||
context.stop()
|
||||
|
||||
assert self.readlines() == (
|
||||
'[{"foo": "bar"},',
|
||||
'{"a": "A", "b": "B", "c": "C"},',
|
||||
'{"foo": "baz"}]',
|
||||
)
|
||||
assert self.readlines() == ('[{"foo": "bar"},', '{"a": "A", "b": "B", "c": "C"},', '{"foo": "baz"}]')
|
||||
|
||||
@incontext()
|
||||
def test_nofields_empty_args(self, context):
|
||||
@ -156,7 +124,7 @@ class JsonWriterTest(Json, WriterTest, TestCase):
|
||||
context.write_sync(EMPTY, EMPTY, EMPTY)
|
||||
context.stop()
|
||||
|
||||
assert self.readlines() == ('[]', )
|
||||
assert self.readlines() == ("[]",)
|
||||
|
||||
|
||||
###
|
||||
@ -165,7 +133,7 @@ class JsonWriterTest(Json, WriterTest, TestCase):
|
||||
|
||||
|
||||
class Ldjson:
|
||||
extension = 'ldjson'
|
||||
extension = "ldjson"
|
||||
ReaderNodeType = LdjsonReader
|
||||
WriterNodeType = LdjsonWriter
|
||||
|
||||
@ -178,85 +146,61 @@ class LdjsonReaderDictsTest(Ldjson, ReaderTest, TestCase):
|
||||
context.write_sync(EMPTY)
|
||||
context.stop()
|
||||
|
||||
assert context.get_buffer() == [
|
||||
({
|
||||
"foo": "bar"
|
||||
}, ),
|
||||
({
|
||||
"baz": "boz"
|
||||
}, ),
|
||||
]
|
||||
assert context.get_buffer() == [({"foo": "bar"},), ({"baz": "boz"},)]
|
||||
|
||||
|
||||
class LdjsonReaderListsTest(Ldjson, ReaderTest, TestCase):
|
||||
input_data = '[1,2,3]\n[4,5,6]'
|
||||
input_data = "[1,2,3]\n[4,5,6]"
|
||||
|
||||
@incontext()
|
||||
def test_nofields(self, context):
|
||||
context.write_sync(EMPTY)
|
||||
context.stop()
|
||||
|
||||
assert context.get_buffer() == [
|
||||
([1, 2, 3], ),
|
||||
([4, 5, 6], ),
|
||||
]
|
||||
assert context.get_buffer() == [([1, 2, 3],), ([4, 5, 6],)]
|
||||
|
||||
@incontext(output_type=tuple)
|
||||
def test_output_type(self, context):
|
||||
context.write_sync(EMPTY)
|
||||
context.stop()
|
||||
|
||||
assert context.get_buffer() == [
|
||||
([1, 2, 3], ),
|
||||
([4, 5, 6], ),
|
||||
]
|
||||
assert context.get_buffer() == [([1, 2, 3],), ([4, 5, 6],)]
|
||||
|
||||
|
||||
class LdjsonReaderStringsTest(Ldjson, ReaderTest, TestCase):
|
||||
input_data = '\n'.join(map(json.dumps, ('foo', 'bar', 'baz')))
|
||||
input_data = "\n".join(map(json.dumps, ("foo", "bar", "baz")))
|
||||
|
||||
@incontext()
|
||||
def test_nofields(self, context):
|
||||
context.write_sync(EMPTY)
|
||||
context.stop()
|
||||
|
||||
assert context.get_buffer() == [
|
||||
('foo', ),
|
||||
('bar', ),
|
||||
('baz', ),
|
||||
]
|
||||
assert context.get_buffer() == [("foo",), ("bar",), ("baz",)]
|
||||
|
||||
@incontext(output_type=tuple)
|
||||
def test_output_type(self, context):
|
||||
context.write_sync(EMPTY)
|
||||
context.stop()
|
||||
|
||||
assert context.get_buffer() == [
|
||||
('foo', ),
|
||||
('bar', ),
|
||||
('baz', ),
|
||||
]
|
||||
assert context.get_buffer() == [("foo",), ("bar",), ("baz",)]
|
||||
|
||||
|
||||
class LdjsonWriterTest(Ldjson, WriterTest, TestCase):
|
||||
@incontext()
|
||||
def test_fields(self, context):
|
||||
context.set_input_fields(['foo', 'bar'])
|
||||
context.write_sync(('a', 'b'), ('c', 'd'))
|
||||
context.set_input_fields(["foo", "bar"])
|
||||
context.write_sync(("a", "b"), ("c", "d"))
|
||||
context.stop()
|
||||
|
||||
assert self.readlines() == ('{"foo": "a", "bar": "b"}', '{"foo": "c", "bar": "d"}')
|
||||
|
||||
@incontext()
|
||||
def test_fields_from_type(self, context):
|
||||
context.set_input_type(namedtuple('Point', 'x y'))
|
||||
context.set_input_type(namedtuple("Point", "x y"))
|
||||
context.write_sync((1, 2), (3, 4))
|
||||
context.stop()
|
||||
|
||||
assert self.readlines() == (
|
||||
'{"x": 1, "y": 2}',
|
||||
'{"x": 3, "y": 4}',
|
||||
)
|
||||
assert self.readlines() == ('{"x": 1, "y": 2}', '{"x": 3, "y": 4}')
|
||||
|
||||
@incontext()
|
||||
def test_nofields_multiple_args(self, context):
|
||||
@ -285,11 +229,7 @@ class LdjsonWriterTest(Ldjson, WriterTest, TestCase):
|
||||
context.write_sync(FOOBAR, OD_ABC, FOOBAZ)
|
||||
context.stop()
|
||||
|
||||
assert self.readlines() == (
|
||||
'{"foo": "bar"}',
|
||||
'{"a": "A", "b": "B", "c": "C"}',
|
||||
'{"foo": "baz"}',
|
||||
)
|
||||
assert self.readlines() == ('{"foo": "bar"}', '{"a": "A", "b": "B", "c": "C"}', '{"foo": "baz"}')
|
||||
|
||||
@incontext()
|
||||
def test_nofields_empty_args(self, context):
|
||||
|
||||
@ -7,21 +7,21 @@ from bonobo.constants import EMPTY
|
||||
from bonobo.execution.contexts.node import NodeExecutionContext
|
||||
from bonobo.util.testing import BufferingNodeExecutionContext, FilesystemTester
|
||||
|
||||
pickle_tester = FilesystemTester('pkl', mode='wb')
|
||||
pickle_tester.input_data = pickle.dumps([['a', 'b', 'c'], ['a foo', 'b foo', 'c foo'], ['a bar', 'b bar', 'c bar']])
|
||||
pickle_tester = FilesystemTester("pkl", mode="wb")
|
||||
pickle_tester.input_data = pickle.dumps([["a", "b", "c"], ["a foo", "b foo", "c foo"], ["a bar", "b bar", "c bar"]])
|
||||
|
||||
|
||||
def test_write_pickled_dict_to_file(tmpdir):
|
||||
fs, filename, services = pickle_tester.get_services_for_writer(tmpdir)
|
||||
|
||||
with NodeExecutionContext(PickleWriter(filename), services=services) as context:
|
||||
context.write_sync({'foo': 'bar'}, {'foo': 'baz', 'ignore': 'this'})
|
||||
context.write_sync({"foo": "bar"}, {"foo": "baz", "ignore": "this"})
|
||||
|
||||
with fs.open(filename, 'rb') as fp:
|
||||
assert pickle.loads(fp.read()) == {'foo': 'bar'}
|
||||
with fs.open(filename, "rb") as fp:
|
||||
assert pickle.loads(fp.read()) == {"foo": "bar"}
|
||||
|
||||
with pytest.raises(AttributeError):
|
||||
getattr(context, 'file')
|
||||
getattr(context, "file")
|
||||
|
||||
|
||||
def test_read_pickled_list_from_file(tmpdir):
|
||||
@ -31,8 +31,5 @@ def test_read_pickled_list_from_file(tmpdir):
|
||||
context.write_sync(EMPTY)
|
||||
|
||||
output = context.get_buffer()
|
||||
assert context.get_output_fields() == ('a', 'b', 'c')
|
||||
assert output == [
|
||||
('a foo', 'b foo', 'c foo'),
|
||||
('a bar', 'b bar', 'c bar'),
|
||||
]
|
||||
assert context.get_output_fields() == ("a", "b", "c")
|
||||
assert output == [("a foo", "b foo", "c foo"), ("a bar", "b bar", "c bar")]
|
||||
|
||||
@ -5,9 +5,9 @@ from unittest.mock import MagicMock
|
||||
import pytest
|
||||
|
||||
import bonobo
|
||||
from bonobo.constants import NOT_MODIFIED, EMPTY
|
||||
from bonobo.util import ensure_tuple, ValueHolder
|
||||
from bonobo.util.testing import BufferingNodeExecutionContext, StaticNodeTest, ConfigurableNodeTest
|
||||
from bonobo.constants import EMPTY, NOT_MODIFIED
|
||||
from bonobo.util import ValueHolder, ensure_tuple
|
||||
from bonobo.util.testing import BufferingNodeExecutionContext, ConfigurableNodeTest, StaticNodeTest
|
||||
|
||||
|
||||
class CountTest(StaticNodeTest, TestCase):
|
||||
@ -26,7 +26,7 @@ class CountTest(StaticNodeTest, TestCase):
|
||||
def test_execution(self):
|
||||
with self.execute() as context:
|
||||
context.write_sync(*([EMPTY] * 42))
|
||||
assert context.get_buffer() == [(42, )]
|
||||
assert context.get_buffer() == [(42,)]
|
||||
|
||||
|
||||
class IdentityTest(StaticNodeTest, TestCase):
|
||||
@ -81,14 +81,14 @@ def test_tee():
|
||||
tee = bonobo.Tee(inner)
|
||||
results = []
|
||||
for i in range(10):
|
||||
results.append(tee('foo'))
|
||||
results.append(tee("foo"))
|
||||
|
||||
assert results == [NOT_MODIFIED] * 10
|
||||
assert len(inner.mock_calls) == 10
|
||||
|
||||
|
||||
def test_noop():
|
||||
assert bonobo.noop(1, 2, 3, 4, foo='bar') == NOT_MODIFIED
|
||||
assert bonobo.noop(1, 2, 3, 4, foo="bar") == NOT_MODIFIED
|
||||
|
||||
|
||||
def test_fixedwindow():
|
||||
@ -98,21 +98,18 @@ def test_fixedwindow():
|
||||
|
||||
with BufferingNodeExecutionContext(bonobo.FixedWindow(2)) as context:
|
||||
context.write_sync(*range(9))
|
||||
assert context.get_buffer() == [(0, 1), (2, 3), (4, 5), (6, 7), (
|
||||
8,
|
||||
None,
|
||||
)]
|
||||
assert context.get_buffer() == [(0, 1), (2, 3), (4, 5), (6, 7), (8, None)]
|
||||
|
||||
with BufferingNodeExecutionContext(bonobo.FixedWindow(1)) as context:
|
||||
context.write_sync(*range(3))
|
||||
assert context.get_buffer() == [(0, ), (1, ), (2, )]
|
||||
assert context.get_buffer() == [(0,), (1,), (2,)]
|
||||
|
||||
|
||||
def test_methodcaller():
|
||||
with BufferingNodeExecutionContext(methodcaller('swapcase')) as context:
|
||||
context.write_sync('aaa', 'bBb', 'CcC')
|
||||
assert context.get_buffer() == list(map(ensure_tuple, ['AAA', 'BbB', 'cCc']))
|
||||
with BufferingNodeExecutionContext(methodcaller("swapcase")) as context:
|
||||
context.write_sync("aaa", "bBb", "CcC")
|
||||
assert context.get_buffer() == list(map(ensure_tuple, ["AAA", "BbB", "cCc"]))
|
||||
|
||||
with BufferingNodeExecutionContext(methodcaller('zfill', 5)) as context:
|
||||
context.write_sync('a', 'bb', 'ccc')
|
||||
assert context.get_buffer() == list(map(ensure_tuple, ['0000a', '000bb', '00ccc']))
|
||||
with BufferingNodeExecutionContext(methodcaller("zfill", 5)) as context:
|
||||
context.write_sync("a", "bb", "ccc")
|
||||
assert context.get_buffer() == list(map(ensure_tuple, ["0000a", "000bb", "00ccc"]))
|
||||
|
||||
@ -8,11 +8,11 @@ from bonobo.util.bags import BagType
|
||||
from bonobo.util.envelopes import Envelope
|
||||
from bonobo.util.testing import BufferingNodeExecutionContext
|
||||
|
||||
MyTuple = namedtuple('MyTuple', ['a', 'b', 'c'])
|
||||
MyBag = BagType('MyBag', ['a', 'b', 'c'])
|
||||
MyTuple = namedtuple("MyTuple", ["a", "b", "c"])
|
||||
MyBag = BagType("MyBag", ["a", "b", "c"])
|
||||
|
||||
|
||||
class MyCustomType():
|
||||
class MyCustomType:
|
||||
def __init__(self, *args):
|
||||
self.args = args
|
||||
|
||||
@ -20,16 +20,19 @@ class MyCustomType():
|
||||
return MyBag(*self.args)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(['factory', 'expected', 'expected_item0'], [
|
||||
[lambda: (1, 2, 3), tuple, int],
|
||||
[lambda: Envelope((1, 2, 3)), tuple, int],
|
||||
[lambda: MyTuple(1, 2, 3), MyTuple, int],
|
||||
[lambda: Envelope(MyTuple(1, 2, 3)), MyTuple, int],
|
||||
[lambda: MyBag(1, 2, 3), MyBag, int],
|
||||
[lambda: Envelope(MyBag(1, 2, 3)), MyBag, int],
|
||||
[lambda: MyCustomType(1, 2, 3), tuple, MyCustomType],
|
||||
[lambda: Envelope(MyCustomType(1, 2, 3)), tuple, MyCustomType],
|
||||
])
|
||||
@pytest.mark.parametrize(
|
||||
["factory", "expected", "expected_item0"],
|
||||
[
|
||||
[lambda: (1, 2, 3), tuple, int],
|
||||
[lambda: Envelope((1, 2, 3)), tuple, int],
|
||||
[lambda: MyTuple(1, 2, 3), MyTuple, int],
|
||||
[lambda: Envelope(MyTuple(1, 2, 3)), MyTuple, int],
|
||||
[lambda: MyBag(1, 2, 3), MyBag, int],
|
||||
[lambda: Envelope(MyBag(1, 2, 3)), MyBag, int],
|
||||
[lambda: MyCustomType(1, 2, 3), tuple, MyCustomType],
|
||||
[lambda: Envelope(MyCustomType(1, 2, 3)), tuple, MyCustomType],
|
||||
],
|
||||
)
|
||||
def test_casts_after_output(factory: Callable, expected, expected_item0):
|
||||
def transform():
|
||||
yield factory()
|
||||
|
||||
@ -1,10 +1,11 @@
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
from whistle import EventDispatcher
|
||||
|
||||
import bonobo
|
||||
from bonobo.execution import events
|
||||
from bonobo.execution.contexts.graph import GraphExecutionContext
|
||||
from bonobo.plugins.console import ConsoleOutputPlugin
|
||||
from whistle import EventDispatcher
|
||||
|
||||
|
||||
def test_register_unregister():
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import pytest
|
||||
|
||||
from unittest.mock import sentinel
|
||||
|
||||
import pytest
|
||||
|
||||
from bonobo.constants import BEGIN
|
||||
from bonobo.structs.graphs import Graph
|
||||
|
||||
@ -48,24 +48,14 @@ def test_graph_add_chain():
|
||||
def test_graph_topological_sort():
|
||||
g = Graph()
|
||||
|
||||
g.add_chain(
|
||||
sentinel.a1,
|
||||
sentinel.a2,
|
||||
sentinel.a3,
|
||||
_input=None,
|
||||
_output=None,
|
||||
)
|
||||
g.add_chain(sentinel.a1, sentinel.a2, sentinel.a3, _input=None, _output=None)
|
||||
|
||||
assert g.topologically_sorted_indexes == (0, 1, 2)
|
||||
assert g[0] == sentinel.a1
|
||||
assert g[1] == sentinel.a2
|
||||
assert g[2] == sentinel.a3
|
||||
|
||||
g.add_chain(
|
||||
sentinel.b1,
|
||||
sentinel.b2,
|
||||
_output=sentinel.a2,
|
||||
)
|
||||
g.add_chain(sentinel.b1, sentinel.b2, _output=sentinel.a2)
|
||||
|
||||
assert g.topologically_sorted_indexes[-2:] == (1, 2)
|
||||
assert g.topologically_sorted_indexes.index(3) < g.topologically_sorted_indexes.index(4)
|
||||
|
||||
@ -19,7 +19,7 @@ from queue import Empty
|
||||
import pytest
|
||||
|
||||
from bonobo.constants import BEGIN, END
|
||||
from bonobo.errors import InactiveWritableError, InactiveReadableError
|
||||
from bonobo.errors import InactiveReadableError, InactiveWritableError
|
||||
from bonobo.structs.inputs import Input
|
||||
|
||||
|
||||
@ -29,22 +29,22 @@ def test_input_runlevels():
|
||||
# Before BEGIN, noone should be able to write in an Input queue.
|
||||
assert not q.alive
|
||||
with pytest.raises(InactiveWritableError):
|
||||
q.put('hello, unborn queue.')
|
||||
q.put("hello, unborn queue.")
|
||||
|
||||
# Begin
|
||||
q.put(BEGIN)
|
||||
assert q.alive and q._runlevel == 1
|
||||
q.put('foo')
|
||||
q.put("foo")
|
||||
|
||||
# Second Begin
|
||||
q.put(BEGIN)
|
||||
assert q.alive and q._runlevel == 2
|
||||
q.put('bar')
|
||||
q.put("bar")
|
||||
q.put(END)
|
||||
|
||||
# FIFO
|
||||
assert q.get() == 'foo'
|
||||
assert q.get() == 'bar'
|
||||
assert q.get() == "foo"
|
||||
assert q.get() == "bar"
|
||||
|
||||
# self.assertEqual(q.alive, False) XXX queue don't know it's dead yet, but it is ...
|
||||
# Async get raises Empty (End is not returned)
|
||||
@ -53,14 +53,14 @@ def test_input_runlevels():
|
||||
assert q.alive
|
||||
|
||||
# Before killing, let's slide some data in.
|
||||
q.put('baz')
|
||||
q.put("baz")
|
||||
|
||||
# Now kill the queue...
|
||||
q.put(END)
|
||||
with pytest.raises(InactiveWritableError):
|
||||
q.put('foo')
|
||||
q.put("foo")
|
||||
|
||||
# Still can get remaining data
|
||||
assert q.get() == 'baz'
|
||||
assert q.get() == "baz"
|
||||
with pytest.raises(InactiveReadableError):
|
||||
q.get()
|
||||
|
||||
@ -2,5 +2,5 @@ from bonobo.structs.tokens import Token
|
||||
|
||||
|
||||
def test_token_repr():
|
||||
t = Token('Acme')
|
||||
assert repr(t) == '<Acme>'
|
||||
t = Token("Acme")
|
||||
assert repr(t) == "<Acme>"
|
||||
|
||||
@ -11,7 +11,7 @@ def test_run_graph_noop():
|
||||
graph = bonobo.Graph(bonobo.noop)
|
||||
assert len(graph) == 1
|
||||
|
||||
with patch('bonobo._api._is_interactive_console', side_effect=lambda: False):
|
||||
with patch("bonobo._api._is_interactive_console", side_effect=lambda: False):
|
||||
result = bonobo.run(graph)
|
||||
|
||||
assert isinstance(result, GraphExecutionContext)
|
||||
|
||||
@ -10,7 +10,7 @@ def generate_integers():
|
||||
|
||||
|
||||
def square(i):
|
||||
return i**2
|
||||
return i ** 2
|
||||
|
||||
|
||||
def results(f, context):
|
||||
|
||||
@ -2,12 +2,12 @@ import inspect
|
||||
|
||||
|
||||
def test_wildcard_import():
|
||||
bonobo = __import__('bonobo')
|
||||
bonobo = __import__("bonobo")
|
||||
assert bonobo.__version__
|
||||
|
||||
for name in dir(bonobo):
|
||||
# ignore attributes starting by underscores
|
||||
if name.startswith('_'):
|
||||
if name.startswith("_"):
|
||||
continue
|
||||
attr = getattr(bonobo, name)
|
||||
if inspect.ismodule(attr):
|
||||
|
||||
@ -1,18 +1,18 @@
|
||||
from bonobo.nodes import CsvReader, JsonReader, CsvWriter, JsonWriter
|
||||
from bonobo import create_reader, create_writer
|
||||
from bonobo.nodes import CsvReader, CsvWriter, JsonReader, JsonWriter
|
||||
|
||||
|
||||
def test_create_reader():
|
||||
t = create_reader('foo.csv')
|
||||
t = create_reader("foo.csv")
|
||||
assert isinstance(t, CsvReader)
|
||||
|
||||
t = create_reader('foo.txt', format='json')
|
||||
t = create_reader("foo.txt", format="json")
|
||||
assert isinstance(t, JsonReader)
|
||||
|
||||
|
||||
def test_create_writer():
|
||||
t = create_writer('foo.csv')
|
||||
t = create_writer("foo.csv")
|
||||
assert isinstance(t, CsvWriter)
|
||||
|
||||
t = create_writer('foo.txt', format='json')
|
||||
t = create_writer("foo.txt", format="json")
|
||||
assert isinstance(t, JsonWriter)
|
||||
|
||||
@ -6,37 +6,37 @@ import pytest
|
||||
|
||||
from bonobo import settings
|
||||
|
||||
TEST_SETTING = 'TEST_SETTING'
|
||||
TEST_SETTING = "TEST_SETTING"
|
||||
|
||||
|
||||
def test_to_bool():
|
||||
assert not settings.to_bool('')
|
||||
assert not settings.to_bool('FALSE')
|
||||
assert not settings.to_bool('NO')
|
||||
assert not settings.to_bool('0')
|
||||
assert not settings.to_bool("")
|
||||
assert not settings.to_bool("FALSE")
|
||||
assert not settings.to_bool("NO")
|
||||
assert not settings.to_bool("0")
|
||||
|
||||
assert settings.to_bool('yup')
|
||||
assert settings.to_bool('True')
|
||||
assert settings.to_bool('yes')
|
||||
assert settings.to_bool('1')
|
||||
assert settings.to_bool("yup")
|
||||
assert settings.to_bool("True")
|
||||
assert settings.to_bool("yes")
|
||||
assert settings.to_bool("1")
|
||||
|
||||
|
||||
def test_setting():
|
||||
s = settings.Setting(TEST_SETTING)
|
||||
assert s.get() is None
|
||||
|
||||
with patch.dict(environ, {TEST_SETTING: 'hello'}):
|
||||
with patch.dict(environ, {TEST_SETTING: "hello"}):
|
||||
assert s.get() is None
|
||||
s.clear()
|
||||
assert s.get() == 'hello'
|
||||
assert s.get() == "hello"
|
||||
|
||||
s = settings.Setting(TEST_SETTING, default='nope')
|
||||
assert s.get() is 'nope'
|
||||
s = settings.Setting(TEST_SETTING, default="nope")
|
||||
assert s.get() is "nope"
|
||||
|
||||
with patch.dict(environ, {TEST_SETTING: 'hello'}):
|
||||
assert s.get() == 'nope'
|
||||
with patch.dict(environ, {TEST_SETTING: "hello"}):
|
||||
assert s.get() == "nope"
|
||||
s.clear()
|
||||
assert s.get() == 'hello'
|
||||
assert s.get() == "hello"
|
||||
|
||||
|
||||
def test_default_settings():
|
||||
@ -45,18 +45,18 @@ def test_default_settings():
|
||||
assert settings.DEBUG.get() is False
|
||||
assert settings.PROFILE.get() is False
|
||||
assert settings.QUIET.get() is False
|
||||
assert settings.LOGGING_LEVEL.get() == logging._checkLevel('INFO')
|
||||
assert settings.LOGGING_LEVEL.get() == logging._checkLevel("INFO")
|
||||
|
||||
with patch.dict(environ, {'DEBUG': 't'}):
|
||||
with patch.dict(environ, {"DEBUG": "t"}):
|
||||
settings.clear_all()
|
||||
assert settings.LOGGING_LEVEL.get() == logging._checkLevel('DEBUG')
|
||||
assert settings.LOGGING_LEVEL.get() == logging._checkLevel("DEBUG")
|
||||
|
||||
settings.clear_all()
|
||||
|
||||
|
||||
def test_check():
|
||||
settings.check()
|
||||
with patch.dict(environ, {'DEBUG': 't', 'PROFILE': 't', 'QUIET': 't'}):
|
||||
with patch.dict(environ, {"DEBUG": "t", "PROFILE": "t", "QUIET": "t"}):
|
||||
settings.clear_all()
|
||||
with pytest.raises(RuntimeError):
|
||||
settings.check()
|
||||
|
||||
@ -1 +1 @@
|
||||
foo = 'bar'
|
||||
foo = "bar"
|
||||
|
||||
@ -16,49 +16,49 @@ from bonobo.util.bags import BagType
|
||||
### Named Tuples
|
||||
################################################################################
|
||||
|
||||
TBag = BagType('TBag', ('x', 'y', 'z')) # type used for pickle tests
|
||||
TBag = BagType("TBag", ("x", "y", "z")) # type used for pickle tests
|
||||
|
||||
|
||||
class TestBagType(unittest.TestCase):
|
||||
def _create(self, *fields, typename='abc'):
|
||||
def _create(self, *fields, typename="abc"):
|
||||
bt = BagType(typename, fields)
|
||||
assert bt._fields == fields
|
||||
assert len(bt._fields) == len(bt._attrs)
|
||||
return bt
|
||||
|
||||
def test_factory(self):
|
||||
Point = BagType('Point', ('x', 'y'))
|
||||
self.assertEqual(Point.__name__, 'Point')
|
||||
Point = BagType("Point", ("x", "y"))
|
||||
self.assertEqual(Point.__name__, "Point")
|
||||
self.assertEqual(Point.__slots__, ())
|
||||
self.assertEqual(Point.__module__, __name__)
|
||||
self.assertEqual(Point.__getitem__, tuple.__getitem__)
|
||||
assert Point._fields == ('x', 'y')
|
||||
assert Point._attrs == ('x', 'y')
|
||||
assert Point._fields == ("x", "y")
|
||||
assert Point._attrs == ("x", "y")
|
||||
|
||||
self.assertRaises(ValueError, BagType, 'abc%', ('efg', 'ghi')) # type has non-alpha char
|
||||
self.assertRaises(ValueError, BagType, 'class', ('efg', 'ghi')) # type has keyword
|
||||
self.assertRaises(ValueError, BagType, '9abc', ('efg', 'ghi')) # type starts with digit
|
||||
self.assertRaises(ValueError, BagType, "abc%", ("efg", "ghi")) # type has non-alpha char
|
||||
self.assertRaises(ValueError, BagType, "class", ("efg", "ghi")) # type has keyword
|
||||
self.assertRaises(ValueError, BagType, "9abc", ("efg", "ghi")) # type starts with digit
|
||||
|
||||
assert self._create('efg', 'g%hi')._attrs == ('efg', 'g_hi')
|
||||
assert self._create('abc', 'class')._attrs == ('abc', '_class')
|
||||
assert self._create('8efg', '9ghi')._attrs == ('_8efg', '_9ghi')
|
||||
assert self._create('_efg', 'ghi')._attrs == ('_efg', 'ghi')
|
||||
assert self._create("efg", "g%hi")._attrs == ("efg", "g_hi")
|
||||
assert self._create("abc", "class")._attrs == ("abc", "_class")
|
||||
assert self._create("8efg", "9ghi")._attrs == ("_8efg", "_9ghi")
|
||||
assert self._create("_efg", "ghi")._attrs == ("_efg", "ghi")
|
||||
|
||||
self.assertRaises(ValueError, BagType, 'abc', ('efg', 'efg', 'ghi')) # duplicate field
|
||||
self.assertRaises(ValueError, BagType, "abc", ("efg", "efg", "ghi")) # duplicate field
|
||||
|
||||
self._create('x1', 'y2', typename='Point0') # Verify that numbers are allowed in names
|
||||
self._create('a', 'b', 'c', typename='_') # Test leading underscores in a typename
|
||||
self._create("x1", "y2", typename="Point0") # Verify that numbers are allowed in names
|
||||
self._create("a", "b", "c", typename="_") # Test leading underscores in a typename
|
||||
|
||||
bt = self._create('a!', 'a?')
|
||||
assert bt._attrs == ('a0', 'a1')
|
||||
x = bt('foo', 'bar')
|
||||
assert x.get('a!') == 'foo'
|
||||
assert x.a0 == 'foo'
|
||||
assert x.get('a?') == 'bar'
|
||||
assert x.a1 == 'bar'
|
||||
bt = self._create("a!", "a?")
|
||||
assert bt._attrs == ("a0", "a1")
|
||||
x = bt("foo", "bar")
|
||||
assert x.get("a!") == "foo"
|
||||
assert x.a0 == "foo"
|
||||
assert x.get("a?") == "bar"
|
||||
assert x.a1 == "bar"
|
||||
|
||||
# check unicode output
|
||||
bt = self._create('the', 'quick', 'brown', 'fox')
|
||||
bt = self._create("the", "quick", "brown", "fox")
|
||||
assert "u'" not in repr(bt._fields)
|
||||
|
||||
self.assertRaises(TypeError, Point._make, [11]) # catch too few args
|
||||
@ -66,33 +66,33 @@ class TestBagType(unittest.TestCase):
|
||||
|
||||
@unittest.skipIf(sys.flags.optimize >= 2, "Docstrings are omitted with -O2 and above")
|
||||
def test_factory_doc_attr(self):
|
||||
Point = BagType('Point', ('x', 'y'))
|
||||
self.assertEqual(Point.__doc__, 'Point(x, y)')
|
||||
Point = BagType("Point", ("x", "y"))
|
||||
self.assertEqual(Point.__doc__, "Point(x, y)")
|
||||
|
||||
@unittest.skipIf(sys.flags.optimize >= 2, "Docstrings are omitted with -O2 and above")
|
||||
def test_doc_writable(self):
|
||||
Point = BagType('Point', ('x', 'y'))
|
||||
Point = BagType("Point", ("x", "y"))
|
||||
self.assertEqual(Point.x.__doc__, "Alias for 'x'")
|
||||
Point.x.__doc__ = 'docstring for Point.x'
|
||||
self.assertEqual(Point.x.__doc__, 'docstring for Point.x')
|
||||
Point.x.__doc__ = "docstring for Point.x"
|
||||
self.assertEqual(Point.x.__doc__, "docstring for Point.x")
|
||||
|
||||
def test_name_fixer(self):
|
||||
for spec, renamed in [
|
||||
[('efg', 'g%hi'), ('efg', 'g_hi')], # field with non-alpha char
|
||||
[('abc', 'class'), ('abc', '_class')], # field has keyword
|
||||
[('8efg', '9ghi'), ('_8efg', '_9ghi')], # field starts with digit
|
||||
[('abc', '_efg'), ('abc', '_efg')], # field with leading underscore
|
||||
[('abc', '', 'x'), ('abc', '_0', 'x')], # fieldname is a space
|
||||
[('&', '¨', '*'), ('_0', '_1', '_2')], # Duplicate attrs, in theory
|
||||
[("efg", "g%hi"), ("efg", "g_hi")], # field with non-alpha char
|
||||
[("abc", "class"), ("abc", "_class")], # field has keyword
|
||||
[("8efg", "9ghi"), ("_8efg", "_9ghi")], # field starts with digit
|
||||
[("abc", "_efg"), ("abc", "_efg")], # field with leading underscore
|
||||
[("abc", "", "x"), ("abc", "_0", "x")], # fieldname is a space
|
||||
[("&", "¨", "*"), ("_0", "_1", "_2")], # Duplicate attrs, in theory
|
||||
]:
|
||||
assert self._create(*spec)._attrs == renamed
|
||||
|
||||
def test_module_parameter(self):
|
||||
NT = BagType('NT', ['x', 'y'], module=collections)
|
||||
NT = BagType("NT", ["x", "y"], module=collections)
|
||||
self.assertEqual(NT.__module__, collections)
|
||||
|
||||
def test_instance(self):
|
||||
Point = self._create('x', 'y', typename='Point')
|
||||
Point = self._create("x", "y", typename="Point")
|
||||
p = Point(11, 22)
|
||||
self.assertEqual(p, Point(x=11, y=22))
|
||||
self.assertEqual(p, Point(11, y=22))
|
||||
@ -101,12 +101,12 @@ class TestBagType(unittest.TestCase):
|
||||
self.assertEqual(p, Point(**dict(x=11, y=22)))
|
||||
self.assertRaises(TypeError, Point, 1) # too few args
|
||||
self.assertRaises(TypeError, Point, 1, 2, 3) # too many args
|
||||
self.assertRaises(TypeError, eval, 'Point(XXX=1, y=2)', locals()) # wrong keyword argument
|
||||
self.assertRaises(TypeError, eval, 'Point(x=1)', locals()) # missing keyword argument
|
||||
self.assertEqual(repr(p), 'Point(x=11, y=22)')
|
||||
self.assertNotIn('__weakref__', dir(p))
|
||||
self.assertRaises(TypeError, eval, "Point(XXX=1, y=2)", locals()) # wrong keyword argument
|
||||
self.assertRaises(TypeError, eval, "Point(x=1)", locals()) # missing keyword argument
|
||||
self.assertEqual(repr(p), "Point(x=11, y=22)")
|
||||
self.assertNotIn("__weakref__", dir(p))
|
||||
self.assertEqual(p, Point._make([11, 22])) # test _make classmethod
|
||||
self.assertEqual(p._fields, ('x', 'y')) # test _fields attribute
|
||||
self.assertEqual(p._fields, ("x", "y")) # test _fields attribute
|
||||
self.assertEqual(p._replace(x=1), (1, 22)) # test _replace method
|
||||
self.assertEqual(p._asdict(), dict(x=11, y=22)) # test _asdict method
|
||||
|
||||
@ -115,13 +115,13 @@ class TestBagType(unittest.TestCase):
|
||||
except ValueError:
|
||||
pass
|
||||
else:
|
||||
self._fail('Did not detect an incorrect fieldname')
|
||||
self._fail("Did not detect an incorrect fieldname")
|
||||
|
||||
p = Point(x=11, y=22)
|
||||
self.assertEqual(repr(p), 'Point(x=11, y=22)')
|
||||
self.assertEqual(repr(p), "Point(x=11, y=22)")
|
||||
|
||||
def test_tupleness(self):
|
||||
Point = BagType('Point', ('x', 'y'))
|
||||
Point = BagType("Point", ("x", "y"))
|
||||
p = Point(11, 22)
|
||||
|
||||
self.assertIsInstance(p, tuple)
|
||||
@ -137,29 +137,29 @@ class TestBagType(unittest.TestCase):
|
||||
|
||||
self.assertEqual(p.x, x)
|
||||
self.assertEqual(p.y, y)
|
||||
self.assertRaises(AttributeError, eval, 'p.z', locals())
|
||||
self.assertRaises(AttributeError, eval, "p.z", locals())
|
||||
|
||||
def test_odd_sizes(self):
|
||||
Zero = BagType('Zero', ())
|
||||
Zero = BagType("Zero", ())
|
||||
self.assertEqual(Zero(), ())
|
||||
self.assertEqual(Zero._make([]), ())
|
||||
self.assertEqual(repr(Zero()), 'Zero()')
|
||||
self.assertEqual(repr(Zero()), "Zero()")
|
||||
self.assertEqual(Zero()._asdict(), {})
|
||||
self.assertEqual(Zero()._fields, ())
|
||||
|
||||
Dot = BagType('Dot', ('d', ))
|
||||
self.assertEqual(Dot(1), (1, ))
|
||||
self.assertEqual(Dot._make([1]), (1, ))
|
||||
Dot = BagType("Dot", ("d",))
|
||||
self.assertEqual(Dot(1), (1,))
|
||||
self.assertEqual(Dot._make([1]), (1,))
|
||||
self.assertEqual(Dot(1).d, 1)
|
||||
self.assertEqual(repr(Dot(1)), 'Dot(d=1)')
|
||||
self.assertEqual(Dot(1)._asdict(), {'d': 1})
|
||||
self.assertEqual(Dot(1)._replace(d=999), (999, ))
|
||||
self.assertEqual(Dot(1)._fields, ('d', ))
|
||||
self.assertEqual(repr(Dot(1)), "Dot(d=1)")
|
||||
self.assertEqual(Dot(1)._asdict(), {"d": 1})
|
||||
self.assertEqual(Dot(1)._replace(d=999), (999,))
|
||||
self.assertEqual(Dot(1)._fields, ("d",))
|
||||
|
||||
n = 5000 if sys.version_info >= (3, 7) else 254
|
||||
names = list(set(''.join([choice(string.ascii_letters) for j in range(10)]) for i in range(n)))
|
||||
names = list(set("".join([choice(string.ascii_letters) for j in range(10)]) for i in range(n)))
|
||||
n = len(names)
|
||||
Big = BagType('Big', names)
|
||||
Big = BagType("Big", names)
|
||||
b = Big(*range(n))
|
||||
self.assertEqual(b, tuple(range(n)))
|
||||
self.assertEqual(Big._make(range(n)), tuple(range(n)))
|
||||
@ -178,14 +178,14 @@ class TestBagType(unittest.TestCase):
|
||||
|
||||
def test_pickle(self):
|
||||
p = TBag(x=10, y=20, z=30)
|
||||
for module in (pickle, ):
|
||||
loads = getattr(module, 'loads')
|
||||
dumps = getattr(module, 'dumps')
|
||||
for module in (pickle,):
|
||||
loads = getattr(module, "loads")
|
||||
dumps = getattr(module, "dumps")
|
||||
for protocol in range(-1, module.HIGHEST_PROTOCOL + 1):
|
||||
q = loads(dumps(p, protocol))
|
||||
self.assertEqual(p, q)
|
||||
self.assertEqual(p._fields, q._fields)
|
||||
self.assertNotIn(b'OrderedDict', dumps(p, protocol))
|
||||
self.assertNotIn(b"OrderedDict", dumps(p, protocol))
|
||||
|
||||
def test_copy(self):
|
||||
p = TBag(x=10, y=20, z=30)
|
||||
@ -197,7 +197,7 @@ class TestBagType(unittest.TestCase):
|
||||
def test_name_conflicts(self):
|
||||
# Some names like "self", "cls", "tuple", "itemgetter", and "property"
|
||||
# failed when used as field names. Test to make sure these now work.
|
||||
T = BagType('T', ('itemgetter', 'property', 'self', 'cls', 'tuple'))
|
||||
T = BagType("T", ("itemgetter", "property", "self", "cls", "tuple"))
|
||||
t = T(1, 2, 3, 4, 5)
|
||||
self.assertEqual(t, (1, 2, 3, 4, 5))
|
||||
newt = t._replace(itemgetter=10, property=20, self=30, cls=40, tuple=50)
|
||||
@ -206,28 +206,194 @@ class TestBagType(unittest.TestCase):
|
||||
# Broader test of all interesting names taken from the code, old
|
||||
# template, and an example
|
||||
words = {
|
||||
'Alias', 'At', 'AttributeError', 'Build', 'Bypass', 'Create', 'Encountered', 'Expected', 'Field', 'For',
|
||||
'Got', 'Helper', 'IronPython', 'Jython', 'KeyError', 'Make', 'Modify', 'Note', 'OrderedDict', 'Point',
|
||||
'Return', 'Returns', 'Type', 'TypeError', 'Used', 'Validate', 'ValueError', 'Variables', 'a', 'accessible',
|
||||
'add', 'added', 'all', 'also', 'an', 'arg_list', 'args', 'arguments', 'automatically', 'be', 'build',
|
||||
'builtins', 'but', 'by', 'cannot', 'class_namespace', 'classmethod', 'cls', 'collections', 'convert',
|
||||
'copy', 'created', 'creation', 'd', 'debugging', 'defined', 'dict', 'dictionary', 'doc', 'docstring',
|
||||
'docstrings', 'duplicate', 'effect', 'either', 'enumerate', 'environments', 'error', 'example', 'exec', 'f',
|
||||
'f_globals', 'field', 'field_names', 'fields', 'formatted', 'frame', 'function', 'functions', 'generate',
|
||||
'getter', 'got', 'greater', 'has', 'help', 'identifiers', 'indexable', 'instance', 'instantiate',
|
||||
'interning', 'introspection', 'isidentifier', 'isinstance', 'itemgetter', 'iterable', 'join', 'keyword',
|
||||
'keywords', 'kwds', 'len', 'like', 'list', 'map', 'maps', 'message', 'metadata', 'method', 'methods',
|
||||
'module', 'module_name', 'must', 'name', 'named', 'namedtuple', 'namedtuple_', 'names', 'namespace',
|
||||
'needs', 'new', 'nicely', 'num_fields', 'number', 'object', 'of', 'operator', 'option', 'p', 'particular',
|
||||
'pickle', 'pickling', 'plain', 'pop', 'positional', 'property', 'r', 'regular', 'rename', 'replace',
|
||||
'replacing', 'repr', 'repr_fmt', 'representation', 'result', 'reuse_itemgetter', 's', 'seen', 'sequence',
|
||||
'set', 'side', 'specified', 'split', 'start', 'startswith', 'step', 'str', 'string', 'strings', 'subclass',
|
||||
'sys', 'targets', 'than', 'the', 'their', 'this', 'to', 'tuple_new', 'type', 'typename', 'underscore',
|
||||
'unexpected', 'unpack', 'up', 'use', 'used', 'user', 'valid', 'values', 'variable', 'verbose', 'where',
|
||||
'which', 'work', 'x', 'y', 'z', 'zip'
|
||||
"Alias",
|
||||
"At",
|
||||
"AttributeError",
|
||||
"Build",
|
||||
"Bypass",
|
||||
"Create",
|
||||
"Encountered",
|
||||
"Expected",
|
||||
"Field",
|
||||
"For",
|
||||
"Got",
|
||||
"Helper",
|
||||
"IronPython",
|
||||
"Jython",
|
||||
"KeyError",
|
||||
"Make",
|
||||
"Modify",
|
||||
"Note",
|
||||
"OrderedDict",
|
||||
"Point",
|
||||
"Return",
|
||||
"Returns",
|
||||
"Type",
|
||||
"TypeError",
|
||||
"Used",
|
||||
"Validate",
|
||||
"ValueError",
|
||||
"Variables",
|
||||
"a",
|
||||
"accessible",
|
||||
"add",
|
||||
"added",
|
||||
"all",
|
||||
"also",
|
||||
"an",
|
||||
"arg_list",
|
||||
"args",
|
||||
"arguments",
|
||||
"automatically",
|
||||
"be",
|
||||
"build",
|
||||
"builtins",
|
||||
"but",
|
||||
"by",
|
||||
"cannot",
|
||||
"class_namespace",
|
||||
"classmethod",
|
||||
"cls",
|
||||
"collections",
|
||||
"convert",
|
||||
"copy",
|
||||
"created",
|
||||
"creation",
|
||||
"d",
|
||||
"debugging",
|
||||
"defined",
|
||||
"dict",
|
||||
"dictionary",
|
||||
"doc",
|
||||
"docstring",
|
||||
"docstrings",
|
||||
"duplicate",
|
||||
"effect",
|
||||
"either",
|
||||
"enumerate",
|
||||
"environments",
|
||||
"error",
|
||||
"example",
|
||||
"exec",
|
||||
"f",
|
||||
"f_globals",
|
||||
"field",
|
||||
"field_names",
|
||||
"fields",
|
||||
"formatted",
|
||||
"frame",
|
||||
"function",
|
||||
"functions",
|
||||
"generate",
|
||||
"getter",
|
||||
"got",
|
||||
"greater",
|
||||
"has",
|
||||
"help",
|
||||
"identifiers",
|
||||
"indexable",
|
||||
"instance",
|
||||
"instantiate",
|
||||
"interning",
|
||||
"introspection",
|
||||
"isidentifier",
|
||||
"isinstance",
|
||||
"itemgetter",
|
||||
"iterable",
|
||||
"join",
|
||||
"keyword",
|
||||
"keywords",
|
||||
"kwds",
|
||||
"len",
|
||||
"like",
|
||||
"list",
|
||||
"map",
|
||||
"maps",
|
||||
"message",
|
||||
"metadata",
|
||||
"method",
|
||||
"methods",
|
||||
"module",
|
||||
"module_name",
|
||||
"must",
|
||||
"name",
|
||||
"named",
|
||||
"namedtuple",
|
||||
"namedtuple_",
|
||||
"names",
|
||||
"namespace",
|
||||
"needs",
|
||||
"new",
|
||||
"nicely",
|
||||
"num_fields",
|
||||
"number",
|
||||
"object",
|
||||
"of",
|
||||
"operator",
|
||||
"option",
|
||||
"p",
|
||||
"particular",
|
||||
"pickle",
|
||||
"pickling",
|
||||
"plain",
|
||||
"pop",
|
||||
"positional",
|
||||
"property",
|
||||
"r",
|
||||
"regular",
|
||||
"rename",
|
||||
"replace",
|
||||
"replacing",
|
||||
"repr",
|
||||
"repr_fmt",
|
||||
"representation",
|
||||
"result",
|
||||
"reuse_itemgetter",
|
||||
"s",
|
||||
"seen",
|
||||
"sequence",
|
||||
"set",
|
||||
"side",
|
||||
"specified",
|
||||
"split",
|
||||
"start",
|
||||
"startswith",
|
||||
"step",
|
||||
"str",
|
||||
"string",
|
||||
"strings",
|
||||
"subclass",
|
||||
"sys",
|
||||
"targets",
|
||||
"than",
|
||||
"the",
|
||||
"their",
|
||||
"this",
|
||||
"to",
|
||||
"tuple_new",
|
||||
"type",
|
||||
"typename",
|
||||
"underscore",
|
||||
"unexpected",
|
||||
"unpack",
|
||||
"up",
|
||||
"use",
|
||||
"used",
|
||||
"user",
|
||||
"valid",
|
||||
"values",
|
||||
"variable",
|
||||
"verbose",
|
||||
"where",
|
||||
"which",
|
||||
"work",
|
||||
"x",
|
||||
"y",
|
||||
"z",
|
||||
"zip",
|
||||
}
|
||||
sorted_words = tuple(sorted(words))
|
||||
T = BagType('T', sorted_words)
|
||||
T = BagType("T", sorted_words)
|
||||
# test __new__
|
||||
values = tuple(range(len(words)))
|
||||
t = T(*values)
|
||||
@ -252,27 +418,39 @@ class TestBagType(unittest.TestCase):
|
||||
self.assertEqual(t.__getnewargs__(), values)
|
||||
|
||||
def test_repr(self):
|
||||
A = BagType('A', ('x', ))
|
||||
self.assertEqual(repr(A(1)), 'A(x=1)')
|
||||
A = BagType("A", ("x",))
|
||||
self.assertEqual(repr(A(1)), "A(x=1)")
|
||||
|
||||
# repr should show the name of the subclass
|
||||
class B(A):
|
||||
pass
|
||||
|
||||
self.assertEqual(repr(B(1)), 'B(x=1)')
|
||||
self.assertEqual(repr(B(1)), "B(x=1)")
|
||||
|
||||
def test_namedtuple_subclass_issue_24931(self):
|
||||
class Point(BagType('_Point', ['x', 'y'])):
|
||||
class Point(BagType("_Point", ["x", "y"])):
|
||||
pass
|
||||
|
||||
a = Point(3, 4)
|
||||
self.assertEqual(a._asdict(), OrderedDict([('x', 3), ('y', 4)]))
|
||||
self.assertEqual(a._asdict(), OrderedDict([("x", 3), ("y", 4)]))
|
||||
|
||||
a.w = 5
|
||||
self.assertEqual(a.__dict__, {'w': 5})
|
||||
self.assertEqual(a.__dict__, {"w": 5})
|
||||
|
||||
def test_annoying_attribute_names(self):
|
||||
self._create(
|
||||
'__slots__', '__getattr__', '_attrs', '_fields', '__new__', '__getnewargs__', '__repr__', '_make', 'get',
|
||||
'_replace', '_asdict', '_cls', 'self', 'tuple'
|
||||
"__slots__",
|
||||
"__getattr__",
|
||||
"_attrs",
|
||||
"_fields",
|
||||
"__new__",
|
||||
"__getnewargs__",
|
||||
"__repr__",
|
||||
"_make",
|
||||
"get",
|
||||
"_replace",
|
||||
"_asdict",
|
||||
"_cls",
|
||||
"self",
|
||||
"tuple",
|
||||
)
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import pytest
|
||||
|
||||
from bonobo.util import sortedlist, ensure_tuple
|
||||
from bonobo.util.collections import tuplize, cast
|
||||
from bonobo.util import ensure_tuple, sortedlist
|
||||
from bonobo.util.collections import cast, tuplize
|
||||
|
||||
|
||||
def test_sortedlist():
|
||||
@ -14,20 +14,20 @@ def test_sortedlist():
|
||||
|
||||
|
||||
def test_ensure_tuple():
|
||||
assert ensure_tuple('a') == ('a', )
|
||||
assert ensure_tuple(('a', )) == ('a', )
|
||||
assert ensure_tuple("a") == ("a",)
|
||||
assert ensure_tuple(("a",)) == ("a",)
|
||||
assert ensure_tuple(()) is ()
|
||||
|
||||
|
||||
@pytest.mark.parametrize('tuplize', [tuplize, cast(tuple)])
|
||||
@pytest.mark.parametrize("tuplize", [tuplize, cast(tuple)])
|
||||
def test_tuplize(tuplize):
|
||||
tuplized_lambda = tuplize(lambda: [1, 2, 3])
|
||||
assert tuplized_lambda() == (1, 2, 3)
|
||||
|
||||
@tuplize
|
||||
def some_generator():
|
||||
yield 'c'
|
||||
yield 'b'
|
||||
yield 'a'
|
||||
yield "c"
|
||||
yield "b"
|
||||
yield "a"
|
||||
|
||||
assert some_generator() == ('c', 'b', 'a')
|
||||
assert some_generator() == ("c", "b", "a")
|
||||
|
||||
@ -17,7 +17,7 @@ def test_deprecated_alias():
|
||||
def foo():
|
||||
pass
|
||||
|
||||
foo = deprecated_alias('bar', foo)
|
||||
foo = deprecated_alias("bar", foo)
|
||||
|
||||
with pytest.warns(DeprecationWarning):
|
||||
foo()
|
||||
|
||||
@ -2,7 +2,7 @@ import operator
|
||||
|
||||
import pytest
|
||||
|
||||
from bonobo.util.objects import Wrapper, get_name, ValueHolder, get_attribute_or_create
|
||||
from bonobo.util.objects import ValueHolder, Wrapper, get_attribute_or_create, get_name
|
||||
from bonobo.util.testing import optional_contextmanager
|
||||
|
||||
|
||||
@ -11,31 +11,31 @@ class foo:
|
||||
|
||||
|
||||
class bar:
|
||||
__name__ = 'baz'
|
||||
__name__ = "baz"
|
||||
|
||||
|
||||
def test_get_name():
|
||||
assert get_name(42) == 'int'
|
||||
assert get_name('eat at joe.') == 'str'
|
||||
assert get_name(str) == 'str'
|
||||
assert get_name(object) == 'object'
|
||||
assert get_name(get_name) == 'get_name'
|
||||
assert get_name(foo) == 'foo'
|
||||
assert get_name(foo()) == 'foo'
|
||||
assert get_name(bar) == 'bar'
|
||||
assert get_name(bar()) == 'baz'
|
||||
assert get_name(42) == "int"
|
||||
assert get_name("eat at joe.") == "str"
|
||||
assert get_name(str) == "str"
|
||||
assert get_name(object) == "object"
|
||||
assert get_name(get_name) == "get_name"
|
||||
assert get_name(foo) == "foo"
|
||||
assert get_name(foo()) == "foo"
|
||||
assert get_name(bar) == "bar"
|
||||
assert get_name(bar()) == "baz"
|
||||
|
||||
|
||||
def test_wrapper_name():
|
||||
assert get_name(Wrapper(42)) == 'int'
|
||||
assert get_name(Wrapper('eat at joe.')) == 'str'
|
||||
assert get_name(Wrapper(str)) == 'str'
|
||||
assert get_name(Wrapper(object)) == 'object'
|
||||
assert get_name(Wrapper(foo)) == 'foo'
|
||||
assert get_name(Wrapper(foo())) == 'foo'
|
||||
assert get_name(Wrapper(bar)) == 'bar'
|
||||
assert get_name(Wrapper(bar())) == 'baz'
|
||||
assert get_name(Wrapper(get_name)) == 'get_name'
|
||||
assert get_name(Wrapper(42)) == "int"
|
||||
assert get_name(Wrapper("eat at joe.")) == "str"
|
||||
assert get_name(Wrapper(str)) == "str"
|
||||
assert get_name(Wrapper(object)) == "object"
|
||||
assert get_name(Wrapper(foo)) == "foo"
|
||||
assert get_name(Wrapper(foo())) == "foo"
|
||||
assert get_name(Wrapper(bar)) == "bar"
|
||||
assert get_name(Wrapper(bar())) == "baz"
|
||||
assert get_name(Wrapper(get_name)) == "get_name"
|
||||
|
||||
|
||||
def test_valueholder():
|
||||
@ -65,10 +65,7 @@ def test_valueholder_notequal():
|
||||
assert not (x != 42)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('rlo,rhi', [
|
||||
(1, 2),
|
||||
('a', 'b'),
|
||||
])
|
||||
@pytest.mark.parametrize("rlo,rhi", [(1, 2), ("a", "b")])
|
||||
def test_valueholder_ordering(rlo, rhi):
|
||||
vlo, vhi = ValueHolder(rlo), ValueHolder(rhi)
|
||||
|
||||
@ -97,15 +94,15 @@ def test_valueholders_containers():
|
||||
assert 5 in x
|
||||
assert 42 not in x
|
||||
|
||||
y = ValueHolder({'foo': 'bar', 'corp': 'acme'})
|
||||
y = ValueHolder({"foo": "bar", "corp": "acme"})
|
||||
|
||||
assert 'foo' in y
|
||||
assert y['foo'] == 'bar'
|
||||
assert "foo" in y
|
||||
assert y["foo"] == "bar"
|
||||
with pytest.raises(KeyError):
|
||||
y['no']
|
||||
y['no'] = 'oh, wait'
|
||||
assert 'no' in y
|
||||
assert 'oh, wait' == y['no']
|
||||
y["no"]
|
||||
y["no"] = "oh, wait"
|
||||
assert "no" in y
|
||||
assert "oh, wait" == y["no"]
|
||||
|
||||
|
||||
def test_get_attribute_or_create():
|
||||
@ -117,27 +114,39 @@ def test_get_attribute_or_create():
|
||||
with pytest.raises(AttributeError):
|
||||
x.foo
|
||||
|
||||
foo = get_attribute_or_create(x, 'foo', 'bar')
|
||||
assert foo == 'bar'
|
||||
assert x.foo == 'bar'
|
||||
foo = get_attribute_or_create(x, "foo", "bar")
|
||||
assert foo == "bar"
|
||||
assert x.foo == "bar"
|
||||
|
||||
foo = get_attribute_or_create(x, 'foo', 'baz')
|
||||
assert foo == 'bar'
|
||||
assert x.foo == 'bar'
|
||||
foo = get_attribute_or_create(x, "foo", "baz")
|
||||
assert foo == "bar"
|
||||
assert x.foo == "bar"
|
||||
|
||||
|
||||
unsupported_operations = {
|
||||
int: {operator.matmul},
|
||||
str: {
|
||||
operator.sub, operator.mul, operator.matmul, operator.floordiv, operator.truediv, operator.mod, divmod,
|
||||
operator.pow, operator.lshift, operator.rshift, operator.and_, operator.xor, operator.or_
|
||||
operator.sub,
|
||||
operator.mul,
|
||||
operator.matmul,
|
||||
operator.floordiv,
|
||||
operator.truediv,
|
||||
operator.mod,
|
||||
divmod,
|
||||
operator.pow,
|
||||
operator.lshift,
|
||||
operator.rshift,
|
||||
operator.and_,
|
||||
operator.xor,
|
||||
operator.or_,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize('x,y', [(5, 3), (0, 10), (0, 0), (1, 1), ('foo', 'bar'), ('', 'baz!')])
|
||||
@pytest.mark.parametrize("x,y", [(5, 3), (0, 10), (0, 0), (1, 1), ("foo", "bar"), ("", "baz!")])
|
||||
@pytest.mark.parametrize(
|
||||
'operation,inplace_operation', [
|
||||
"operation,inplace_operation",
|
||||
[
|
||||
(operator.add, operator.iadd),
|
||||
(operator.sub, operator.isub),
|
||||
(operator.mul, operator.imul),
|
||||
@ -152,14 +161,14 @@ unsupported_operations = {
|
||||
(operator.and_, operator.iand),
|
||||
(operator.xor, operator.ixor),
|
||||
(operator.or_, operator.ior),
|
||||
]
|
||||
],
|
||||
)
|
||||
def test_valueholder_integer_operations(x, y, operation, inplace_operation):
|
||||
v = ValueHolder(x)
|
||||
|
||||
is_supported = operation not in unsupported_operations.get(type(x), set())
|
||||
|
||||
isdiv = ('div' in operation.__name__) or ('mod' in operation.__name__)
|
||||
isdiv = ("div" in operation.__name__) or ("mod" in operation.__name__)
|
||||
|
||||
# forward...
|
||||
with optional_contextmanager(pytest.raises(TypeError), ignore=is_supported):
|
||||
|
||||
@ -3,16 +3,16 @@ from bonobo.util.resolvers import _parse_option, _resolve_options, _resolve_tran
|
||||
|
||||
|
||||
def test_parse_option():
|
||||
assert _parse_option('foo=bar') == ('foo', 'bar')
|
||||
assert _parse_option('foo="bar"') == ('foo', 'bar')
|
||||
assert _parse_option('sep=";"') == ('sep', ';')
|
||||
assert _parse_option('foo') == ('foo', True)
|
||||
assert _parse_option("foo=bar") == ("foo", "bar")
|
||||
assert _parse_option('foo="bar"') == ("foo", "bar")
|
||||
assert _parse_option('sep=";"') == ("sep", ";")
|
||||
assert _parse_option("foo") == ("foo", True)
|
||||
|
||||
|
||||
def test_resolve_options():
|
||||
assert _resolve_options(('foo=bar', 'bar="baz"')) == {'foo': 'bar', 'bar': 'baz'}
|
||||
assert _resolve_options(("foo=bar", 'bar="baz"')) == {"foo": "bar", "bar": "baz"}
|
||||
assert _resolve_options() == {}
|
||||
|
||||
|
||||
def test_resolve_transformations():
|
||||
assert _resolve_transformations(('PrettyPrinter', )) == (bonobo.PrettyPrinter, )
|
||||
assert _resolve_transformations(("PrettyPrinter",)) == (bonobo.PrettyPrinter,)
|
||||
|
||||
@ -3,12 +3,9 @@ from bonobo.util.statistics import WithStatistics
|
||||
|
||||
class MyThingWithStats(WithStatistics):
|
||||
def get_statistics(self, *args, **kwargs):
|
||||
return (
|
||||
('foo', 42),
|
||||
('bar', 69),
|
||||
)
|
||||
return (("foo", 42), ("bar", 69))
|
||||
|
||||
|
||||
def test_with_statistics():
|
||||
o = MyThingWithStats()
|
||||
assert o.get_statistics_as_string() == 'foo=42 bar=69'
|
||||
assert o.get_statistics_as_string() == "foo=42 bar=69"
|
||||
|
||||
Reference in New Issue
Block a user