def test_read_empty_yaml_file_and_get_default(): def check_empty(filename): yaml = YamlFile(filename) value = yaml.get_value(["a", "z"], "default") assert "default" == value with_file_contents("", check_empty)
def test_read_corrupted_yaml_file(): def check_corrupted(filename): yaml = YamlFile(filename) assert yaml.corrupted assert "mapping values are not allowed here" in yaml.corrupted_error_message # it should raise an exception if you try to modify with pytest.raises(ValueError) as excinfo: yaml.set_value(["foo", "bar"], 42) assert "Cannot modify corrupted" in repr(excinfo.value) with pytest.raises(ValueError) as excinfo: yaml.save() assert "Cannot modify corrupted" in repr(excinfo.value) # the file should appear empty if you try to get anything, # but it shouldn't throw assert yaml._yaml is not None assert yaml.get_value(["a", "b"]) is None with_file_contents(""" ^ a: b: c """, check_corrupted)
def test_read_yaml_file_and_add_section(): original_content = """ a: b: c """ def add_section(filename): yaml = YamlFile(filename) value = yaml.get_value(["a", "b"]) assert "c" == value yaml.set_value(["x", "y"], dict(z=42, q="rs")) assert yaml.change_count == 1 yaml.save() assert yaml.change_count == 2 yaml2 = YamlFile(filename) value2 = yaml2.get_value(["a", "b"]) assert "c" == value2 added_value = yaml2.get_value(["x", "y", "z"]) assert 42 == added_value added_value_2 = yaml2.get_value(["x", "y", "q"]) assert "rs" == added_value_2 print(open(filename, 'r').read()) with_file_contents(original_content, add_section)
def test_load_requirements_txt(): def check(filename): spec = _load_requirements_txt(filename) assert spec is not None assert spec.name == 'default' assert spec.conda_packages == () assert spec.channels == () assert spec.pip_packages == ('MyApp', 'Framework==0.9.4', 'Library>=0.2', 'svn+http://myrepo/svn/MyThing#egg=MyThing') assert spec.pip_package_names_set == set(('MyApp', 'Framework', 'Library', 'MyThing')) assert spec.logical_hash == '784ba385d4cd468756e3cbc57f33e97afdc38059' with_file_contents( """ MyApp # Comment; this is a framework Framework==0.9.4 # blank line above this indented comment! Library>=0.2 -e svn+http://myrepo/svn/MyThing#egg=MyThing --index-url http://example.com/private-pypi/ --find-links http://example.com/private-packages/ """, check)
def test_load_environment_yml_with_prefix(): def check(filename): spec = _load_environment_yml(filename) assert spec is not None assert spec.name == 'foo' assert spec.conda_packages == ('bar=1.0', 'baz') assert spec.pip_packages == ('pippy', 'poppy==2.0') assert spec.channels == ('channel1', 'channel2') assert spec.logical_hash == 'e91a2263df510c9b188b132b801ba53aa99cc407' with_file_contents( """ prefix: /opt/foo dependencies: - bar=1.0 - baz - pip: - pippy - poppy==2.0 channels: - channel1 - channel2 """, check)
def test_roundtrip_yaml_file_preserving_order_and_comments(): original_content = """ # comment in front of a a: x: y # comment in front of z z: q b: i: j # whitespace in front of this comment in front of k k: l c: # comment before a list item - foo - bar # comment after a list item d: hello: world foo: bar e: woot: woot # comment at the end of e # comment in column 0 at the end # this one is a block comment # which continues several lines """ def check_roundtrip(filename): yaml = YamlFile(filename) yaml._previous_content = "not the actual previous content" yaml.save() new_content = open(filename, 'r').read() print("the re-saved version of the file was:") print(new_content) assert original_content != new_content # We don't require that the YAML backend preserves every # formatting detail, but it can't reorder things or lose # comments because if it did users would be annoyed. # Minor whitespace changes are OK, though ideally we'd # avoid even those. def canonicalize(content): if content.startswith("\n"): content = content[1:] return content.replace(" ", "").replace("\n\n", "\n") original_canon = canonicalize(original_content) new_canon = canonicalize(new_content) assert original_canon == new_canon with_file_contents(original_content, check_roundtrip)
def test_read_yaml_file_and_get_default_due_to_non_dict_section(): def check_a(filename): yaml = YamlFile(filename) value = yaml.get_value(["a", "b"], "default") assert "default" == value with_file_contents(""" a: 42 """, check_a)
def test_read_yaml_file_and_get_list_valued_section(): def get_list_value(filename): yaml = YamlFile(filename) value = yaml.get_value("a") assert [1, 2, 3] == value with_file_contents(""" a: [1,2,3] """, get_list_value)
def test_read_yaml_file_and_get_default_due_to_missing_section(): def check_abc(filename): yaml = YamlFile(filename) value = yaml.get_value(["z", "b"], "default") assert "default" == value with_file_contents(""" a: b: c """, check_abc)
def test_read_yaml_file_and_unset_values(): # testing single-item dict, two-item dict, and toplevel value original_content = """ a: b: 1 x: y: 2 z: 3 q: 4 """ def unset_values(filename): yaml = YamlFile(filename) assert yaml.change_count == 1 a_b = yaml.get_value(["a", "b"]) assert 1 == a_b x_y = yaml.get_value(["x", "y"]) assert 2 == x_y x_z = yaml.get_value(["x", "z"]) assert 3 == x_z q = yaml.get_value("q") assert 4 == q def assert_unset_on_reload(path): yaml2 = YamlFile(filename) assert yaml2.change_count == 1 value2 = yaml2.get_value(path, None) assert value2 is None scope = dict(last_change=yaml.change_count) def check_unset(path): assert yaml.change_count == scope['last_change'] assert not yaml.has_unsaved_changes yaml.unset_value(path) assert yaml.get_value(path, None) is None assert yaml.has_unsaved_changes yaml.save() assert yaml.change_count == (scope['last_change'] + 1) scope['last_change'] += 1 assert_unset_on_reload(path) check_unset(["a", "b"]) check_unset(["x", "y"]) check_unset(["x", "z"]) check_unset("q") assert not yaml.has_unsaved_changes yaml.unset_value("not_in_there") assert not yaml.has_unsaved_changes with_file_contents(original_content, unset_values)
def test_invalid_path(): def check_bad_path(filename): yaml = YamlFile(filename) assert not yaml.corrupted with pytest.raises(ValueError) as excinfo: yaml.get_value(42) assert "YAML file path must be a string or an iterable of strings" in repr(excinfo.value) with_file_contents(""" a: b: c """, check_bad_path)
def test_load_environment_yml_with_broken_sections(): def check(filename): spec = _load_environment_yml(filename) assert spec is not None assert spec.name == 'foo' assert spec.conda_packages == () assert spec.pip_packages == () assert spec.channels == () with_file_contents(""" name: foo dependencies: 42 channels: 57 """, check)
def test_read_yaml_file_and_set_get_empty_string(): def check(filename): yaml = YamlFile(filename) assert not yaml.corrupted assert yaml.corrupted_error_message is None assert yaml.change_count == 1 value = yaml.get_value("a", None) assert value is None yaml.set_value("a", '') value = yaml.get_value("a", None) assert value == '' # only-whitespace string yaml.set_value("a", ' ') value = yaml.get_value("a", None) assert value == ' ' with_file_contents("", check)
def test_save_environment_yml(): def check_save(spec, dirname): saved = os.path.join(dirname, 'saved.yml') spec.save_environment_yml(saved) spec2 = _load_environment_yml(saved) assert spec2 is not None assert spec2.name == 'foo' assert spec2.conda_packages == ('xyz', 'bar=1.0', 'baz', 'abc') assert spec2.pip_packages == ('pippy', 'poppy==2.0') assert spec2.channels == ('channel1', 'channel2') assert spec2.logical_hash == 'ee1be9dc875857a69ccabb96cb45b5b828a6dff9' def check(filename): spec = _load_environment_yml(filename) assert spec is not None assert spec.name == 'foo' assert spec.conda_packages == ('xyz', 'bar=1.0', 'baz', 'abc') assert spec.pip_packages == ('pippy', 'poppy==2.0') assert spec.channels == ('channel1', 'channel2') assert spec.logical_hash == 'ee1be9dc875857a69ccabb96cb45b5b828a6dff9' with_directory_contents({}, lambda dirname: check_save(spec, dirname)) with_file_contents( """ name: foo dependencies: - xyz - bar=1.0 - baz - abc - pip: - pippy - poppy==2.0 channels: - channel1 - channel2 """, check)
def test_read_yaml_file_and_change_value(): # ruamel.yaml does reformat yaml files a little bit, # for example it picks its own indentation, even # as it tries to keep comments and stuff. So # this test cheats by using input that happens # to be in the format ruamel.yaml will generate. # Oh well. template = """ # this is a comment 1 a: # this is a comment 2 b: %s """ template = template[1:] # chop leading newline original_value = "c" original_content = template % (original_value) changed_value = 42 changed_content = template % (changed_value) def change_abc(filename): yaml = YamlFile(filename) assert yaml.change_count == 1 value = yaml.get_value(["a", "b"]) assert original_value == value yaml.set_value(["a", "b"], changed_value) yaml.save() import codecs with codecs.open(filename, 'r', 'utf-8') as file: changed = file.read() assert changed_content == changed yaml2 = YamlFile(filename) assert yaml2.change_count == 1 value2 = yaml2.get_value(["a", "b"]) assert changed_value == value2 with_file_contents(original_content, change_abc)
def test_read_yaml_file_and_get_value(): def check_abc(filename): yaml = YamlFile(filename) assert not yaml.corrupted assert yaml.corrupted_error_message is None assert yaml.change_count == 1 # try getting with a list of keys value = yaml.get_value(["a", "b"]) assert "c" == value # get a single string as the path value = yaml.get_value("a") assert dict(b="c") == value # get with a tuple to show we aren't list-specific value = yaml.get_value(("a", "b")) assert "c" == value assert yaml.root == dict(a=dict(b='c')) with_file_contents(""" a: b: c """, check_abc)
def test_load_environment_yml_no_name(): def check(filename): spec = _load_environment_yml(filename) assert spec is not None assert spec.name == os.path.basename(filename) assert spec.conda_packages == ('bar=1.0', 'baz') assert spec.pip_packages == ('pippy', 'poppy==2.0') assert spec.channels == ('channel1', 'channel2') assert spec.channels_and_packages_hash == 'e91a2263df510c9b188b132b801ba53aa99cc407' with_file_contents( """ dependencies: - bar=1.0 - baz - pip: - pippy - poppy==2.0 channels: - channel1 - channel2 """, check)