def test_scalar_collectors(self, quiet_logger, yamlpath, results): yamldata = """--- list1: - 1 - 2 - 3 list2: - 4 - 5 - 6 exclude: - 3 - 4 """ yaml = YAML() processor = Processor(quiet_logger, yaml.load(yamldata)) matchidx = 0 # Note that Collectors deal with virtual DOMs, so mustexist must always # be set True. Otherwise, ephemeral virtual nodes would be created and # discarded. Is this desirable? Maybe, but not today. For now, using # Collectors without setting mustexist=True will be undefined behavior. for node in processor.get_nodes(yamlpath, mustexist=True): assert unwrap_node_coords(node) == results[matchidx] matchidx += 1 assert len(results) == matchidx
def test_get_every_data_type(self, quiet_logger): # Contributed by https://github.com/AndydeCleyre yamldata = """--- intthing: 6 floatthing: 6.8 yesthing: yes nothing: no truething: true falsething: false nullthing: null nothingthing: emptystring: "" nullstring: "null" """ results = [6, 6.8, "yes", "no", True, False, None, None, "", "null"] yaml = YAML() data = yaml.load(yamldata) processor = Processor(quiet_logger, data) yamlpath = YAMLPath("*") match_index = 0 for node in processor.get_nodes(yamlpath): assert unwrap_node_coords(node) == results[match_index] match_index += 1
def test_set_value(self, quiet_logger, yamlpath, value, tally, mustexist, vformat, pathsep): yamldata = """--- aliases: - &testAnchor Initial Value top_array: # Comment 1 - 1 # Comment 2 - 2 # Comment N top_scalar: Top-level plain scalar string top_hash: positive_float: 3.14159265358 negative_float: -11.034 null_value: """ yaml = YAML() data = yaml.load(yamldata) processor = Processor(quiet_logger, data) processor.set_value(yamlpath, value, mustexist=mustexist, value_format=vformat, pathsep=pathsep) matchtally = 0 for node in processor.get_nodes(yamlpath, mustexist=mustexist): assert unwrap_node_coords(node) == value matchtally += 1 assert matchtally == tally
def test_set_nonunique_values(self, quiet_logger, yamlpath, value, verifications): yamldata = """--- aliases: - &alias_number 1 - &alias_bool true number: 1 bool: true alias_number: *alias_number alias_bool: *alias_bool hash: number: 1 bool: true alias_number: *alias_number alias_bool: *alias_bool complex: hash: number: 1 bool: true alias_number: *alias_number alias_bool: *alias_bool """ yaml = YAML() data = yaml.load(yamldata) processor = Processor(quiet_logger, data) processor.set_value(yamlpath, value) for verification in verifications: for verify_node_coord in processor.get_nodes(verification[0]): assert unwrap_node_coords(verify_node_coord) == verification[1]
def test_key_anchor_changes(self, quiet_logger, yamlpath, value, tally, mustexist, vformat, pathsep): yamldata = """--- anchorKeys: &keyOne aliasOne: 11A1 &keyTwo aliasTwo: 22B2 &recursiveAnchorKey subjectKey: *recursiveAnchorKey hash: *keyOne : subval: 1.1 *keyTwo : subval: 2.2 *recursiveAnchorKey : subval: 3.3 """ yaml = YAML() data = yaml.load(yamldata) processor = Processor(quiet_logger, data) yamlpath = YAMLPath(yamlpath) processor.set_value(yamlpath, value, mustexist=mustexist, value_format=vformat, pathsep=pathsep) matchtally = 0 for node in processor.get_nodes(yamlpath): assert unwrap_node_coords(node) == value matchtally += 1 assert matchtally == tally
def test_happy_get_eyaml_values(self, quiet_logger, eyamldata_f, old_eyaml_keys, yaml_path, compare): processor = EYAMLProcessor(quiet_logger, eyamldata_f, privatekey=old_eyaml_keys[0], publickey=old_eyaml_keys[1]) for node in processor.get_eyaml_values(yaml_path, True): assert unwrap_node_coords(node) == compare
def test_enforce_pathsep(self, quiet_logger): yamldata = """--- aliases: - &aliasAnchorOne Anchored Scalar Value """ yaml = YAML() processor = Processor(quiet_logger, yaml.load(yamldata)) yamlpath = YAMLPath("aliases[&aliasAnchorOne]") for node in processor.get_nodes(yamlpath, pathsep=PathSeperators.FSLASH): assert unwrap_node_coords(node) == "Anchored Scalar Value"
def test_delete_nodes(self, quiet_logger, delete_yamlpath, pathseperator, old_deleted_nodes, new_flat_data): yamldata = """--- aliases: - &alias_number 1 - &alias_bool true number: 1 bool: true alias_number: *alias_number alias_bool: *alias_bool hash: number: 1 bool: true alias_number: *alias_number alias_bool: *alias_bool complex: hash: number: 1 bool: true alias_number: *alias_number alias_bool: *alias_bool records: - id: ABC data: 123 - id: BCD data: 987 - id: CDE data: 8B8 """ yaml = YAML() data = yaml.load(yamldata) processor = Processor(quiet_logger, data) # The return set must be received lest no nodes will be deleted deleted_nodes = [] for nc in processor.delete_nodes(delete_yamlpath, pathsep=pathseperator): deleted_nodes.append(nc) for (test_value, verify_node_coord) in zip(old_deleted_nodes, deleted_nodes): assert test_value, unwrap_node_coords(verify_node_coord) for (test_value, verify_node_coord) in zip(new_flat_data, processor.get_nodes("**")): assert test_value, unwrap_node_coords(verify_node_coord)
def test_preserve_old_blockiness(self, quiet_logger, eyamldata_f, old_eyaml_keys, yaml_path, newval, eoformat, yvformat): processor = EYAMLProcessor(quiet_logger, eyamldata_f, privatekey=old_eyaml_keys[0], publickey=old_eyaml_keys[1]) processor.set_eyaml_value(yaml_path, newval, output=eoformat) encvalue = None encformat = YAMLValueFormats.DEFAULT for encnode in processor.get_nodes(yaml_path): encvalue = unwrap_node_coords(encnode) encformat = YAMLValueFormats.from_node(encvalue) break assert EYAMLProcessor.is_eyaml_value( encvalue) and yvformat == encformat
def test_happy_set_eyaml_value(self, quiet_logger, eyamldata_f, old_eyaml_keys, yaml_path, compare, mustexist, output_format): processor = EYAMLProcessor(quiet_logger, eyamldata_f, privatekey=old_eyaml_keys[0], publickey=old_eyaml_keys[1]) # Set the test value processor.set_eyaml_value(yaml_path, compare, output_format, mustexist) # Ensure the new value is encrypted encvalue = None for encnode in processor.get_nodes(yaml_path): encvalue = unwrap_node_coords(encnode) break assert EYAMLProcessor.is_eyaml_value(encvalue)
def test_key_anchor_children(self, quiet_logger): yamldata = """--- anchorKeys: &keyOne aliasOne: 1 1 Alpha 1 &keyTwo aliasTwo: 2 2 Beta 2 hash: *keyOne : subval: 1.1 *keyTwo : subval: 2.2 """ yaml = YAML() data = yaml.load(yamldata) processor = Processor(quiet_logger, data) yamlpath = YAMLPath("hash[&keyTwo].subval") newvalue = "Mute audibles" processor.set_value(yamlpath, newvalue, mustexist=True) matchtally = 0 for node in processor.get_nodes(yamlpath): assert unwrap_node_coords(node) == newvalue matchtally += 1 assert matchtally == 1
def test_get_nodes(self, quiet_logger, yamlpath, results, mustexist, default): yamldata = """--- aliases: - &aliasAnchorOne Anchored Scalar Value - &aliasAnchorTwo Hey, Number Two! array_of_hashes: &arrayOfHashes - step: 1 name: one - step: 2 name: two rollback_hashes: on_condition: failure: - step: 3 name: three - step: 4 name: four disabled_steps: - 2 - 3 squads: alpha: 1.1 bravo: 2.2 charlie: 3.3 delta: 4.4 number_keys: 1: one 2: two 3: three # For traversal tests: name: Name 0-0 lots_of_names: name: Name 1-1 tier1: name: Name 2-1 tier2: name: Name 3-1 list_of_named_objects: - name: Name 4-1 tag: Tag 4-1 other: Other 4-1 dude: Dude 4-1 - tag: Tag 4-2 name: Name 4-2 dude: Dude 4-2 other: Other 4-2 - other: Other 4-3 dude: Dude 4-3 tag: Tag 4-3 name: Name 4-3 - dude: Dude 4-4 tag: Tag 4-4 name: Name 4-4 other: Other 4-4 ############################################################################### # For descendent searching: products_hash: doodad: availability: start: date: 2020-10-10 time: 08:00 stop: date: 2020-10-29 time: 17:00 dimensions: width: 5 height: 5 depth: 5 weight: 10 doohickey: availability: start: date: 2020-08-01 time: 10:00 stop: date: 2020-09-25 time: 10:00 dimensions: width: 1 height: 2 depth: 3 weight: 4 widget: availability: start: date: 2020-01-01 time: 12:00 stop: date: 2020-01-01 time: 16:00 dimensions: width: 9 height: 10 depth: 1 weight: 4 products_array: - product: doodad availability: start: date: 2020-10-10 time: 08:00 stop: date: 2020-10-29 time: 17:00 dimensions: width: 5 height: 5 depth: 5 weight: 10 - product: doohickey availability: start: date: 2020-08-01 time: 10:00 stop: date: 2020-09-25 time: 10:00 dimensions: width: 1 height: 2 depth: 3 weight: 4 - product: widget availability: start: date: 2020-01-01 time: 12:00 stop: date: 2020-01-01 time: 16:00 dimensions: width: 9 height: 10 depth: 1 weight: 4 ############################################################################### """ yaml = YAML() processor = Processor(quiet_logger, yaml.load(yamldata)) matchidx = 0 for node in processor.get_nodes( yamlpath, mustexist=mustexist, default_value=default ): assert unwrap_node_coords(node) == results[matchidx] matchidx += 1 assert len(results) == matchidx
def test_good_multi_replacements(self, script_runner, tmp_path_factory, old_eyaml_keys, new_eyaml_keys, quiet_logger): from yamlpath.func import unwrap_node_coords from yamlpath.common import Parsers from yamlpath import Processor from yamlpath.eyaml import EYAMLProcessor simple_content = """--- encrypted_string: ENC[PKCS7,MIIBiQYJKoZIhvcNAQcDoIIBejCCAXYCAQAxggEhMIIBHQIBADAFMAACAQEwDQYJKoZIhvcNAQEBBQAEggEAHA4rPcTzvgzPLtnGz3yoyX/kVlQ5TnPXcScXK2bwjguGZLkuzv/JVPAsOm4t6GlnROpy4zb/lUMHRJDChJhPLrSj919B8//huoMgw0EU5XTcaN6jeDDjL+vhjswjvLFOux66UwvMo8sRci/e2tlFiam8VgxzV0hpF2qRrL/l84V04gL45kq4PCYDWrJNynOwYVbSIF+qc5HaF25H8kHq1lD3RB6Ob/J942Q7k5Qt7W9mNm9cKZmxwgtUgIZWXW6mcPJ2dXDB/RuPJJSrLsb1VU/DkhdgxaNzvLCA+MViyoFUkCfHFNZbaHKNkoYXBy7dLmoh/E5tKv99FeG/7CzL3DBMBgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBCVU5Mjt8+4dLkoqB9YArfkgCDkdIhXR9T1M4YYa1qTE6by61VPU3g1aMExRmo4tNZ8FQ==] encrypted_block: > ENC[PKCS7,MIIBeQYJKoZIhvcNAQcDoIIBajCCAWYCAQAxggEhMIIBHQIBADAFMAACAQEw DQYJKoZIhvcNAQEBBQAEggEAnxQVqyIgRTb/+VP4Q+DLJcnlS8YPouXEW8+z it9uwUA02CEPxCEU944GcHpgTY3EEtkm+2Z/jgXI119VMML+OOQ1NkwUiAw/ wq0vwz2D16X31XzhedQN5FZbfZ1C+2tWSQfCjE0bu7IeHfyR+k2ssD11kNZh JDEr2bM2dwOdT0y7VGcQ06vI9gw6UXcwYAgS6FoLm7WmFftjcYiNB+0EJSW0 VcTn2gveaw9iOQcum/Grby+9Ybs28fWd8BoU+ZWDpoIMEceujNa9okIXNPJO jcvv1sgauwJ3RX6WFQIy/beS2RT5EOLhWIZCAQCcgJWgovu3maB7dEUZ0NLG OYUR7zA8BgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBAbO16EzQ5/cdcvgB0g tpKIgBAEgTLT5n9Jtc9venK0CKso] """ anchored_content = """--- aliases: - &blockStyle > ENC[PKCS7,MIIBiQYJKoZIhvcNAQcDoIIBejCCAXYCAQAxggEhMIIBHQIBADAFMAACAQEw DQYJKoZIhvcNAQEBBQAEggEArvk6OYa1gACTdrWq2SpCrtGRlc61la5AGU7L aLTyKfqD9vqx71RDjobfOF96No07kLsEpoAJ+LKKHNjdG6kjvpGPmttj9Dkm XVoU6A+YCmm4iYFKD/NkoSOEyAkoDOXSqdjrgt0f37GefEsXt6cqAavDpUJm pmc0KI4TCG5zpfCxqttMs+stOY3Y+0WokkulQujZ7K3SdWUSHIysgMrWiect Wdg5unxN1A/aeyvhgvYSNPjU9KBco7SDnigSs9InW/QghJFrZRrDhTp1oTUc qK5lKvaseHkVGi91vPWeLQxZt1loJB5zL6j5BxMbvRfJK+wc3ax2u4x8WTAB EurCwzBMBgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBAwcy7jvcOGcMfLEtug LEXbgCBkocdckuDe14mVGmUmM++xN34OEVRCeGVWWUnWq1DJ4Q==] - &stringStyle ENC[PKCS7,MIIBiQYJKoZIhvcNAQcDoIIBejCCAXYCAQAxggEhMIIBHQIBADAFMAACAQEwDQYJKoZIhvcNAQEBBQAEggEAIu44u62q5sVfzC7kytLi2Z/EzH2DKr4vDsoqDBeSZ71aRku/uSrjyiO4lyoq9Kva+eBAyjBay5fnqPVBaU3Rud2pdEoZEoyofi02jn4hxUKpAO1W0AUgsQolGe53qOdM4U8RbwnTR0gr3gp2mCd18pH3SRMP9ryrsBAxGzJ6mR3RgdZnlTlqVGXCeWUeVpbH+lcHw3uvd+o/xkvJ/3ypxz+rWILiAZ3QlCirzn/qb2fHuKf3VBh8RVFuQDaM5voajZlgjD6KzNCsbATOqOA6eJI4j0ngPdDlIjGHAnahuyluQ5f5SIaIjLC+ZeCOfIYni0MQ+BHO0JNbccjq2Unb7TBMBgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBCYmAI0Ao3Ok1cSmVw0SgQGgCBK62z1r5RfRjf1xKfqDxTsGUHfsUmM3EjGJfnWzCRvuQ==] block: *blockStyle string: *stringStyle yet_another: 'more.complex.child': *blockStyle """ simple_file = create_temp_yaml_file(tmp_path_factory, simple_content) anchored_file = create_temp_yaml_file(tmp_path_factory, anchored_content) result = script_runner.run( self.command, "--newprivatekey={}".format(new_eyaml_keys[0]), "--newpublickey={}".format(new_eyaml_keys[1]), "--oldprivatekey={}".format(old_eyaml_keys[0]), "--oldpublickey={}".format(old_eyaml_keys[1]), simple_file, anchored_file ) assert result.success, result.stderr with open(simple_file, 'r') as fhnd: simple_data = fhnd.read() with open(anchored_file, 'r') as fhnd: anchored_data = fhnd.read() assert not simple_data == simple_content assert not anchored_data == anchored_content # Verify that block and string formatting is correct yaml = Parsers.get_yaml_editor() (yaml_rotated_data, doc_loaded) = Parsers.get_yaml_data( yaml, quiet_logger, anchored_data, literal=True) if not doc_loaded: # An error message has already been logged assert False, "Rotated anchored data failed to load" source_processor = Processor(quiet_logger, yaml_rotated_data) for node in source_processor.get_nodes('/block', mustexist=True): assert not ' ' in unwrap_node_coords(node) # Test that the pre- and post-rotated values are identical (yaml_anchored_data, doc_loaded) = Parsers.get_yaml_data( yaml, quiet_logger, anchored_content, literal=True) if not doc_loaded: # An error message has already been logged assert False, "Original anchored data failed to load" (yaml_rotated_data, doc_loaded) = Parsers.get_yaml_data( yaml, quiet_logger, anchored_data, literal=True) if not doc_loaded: # An error message has already been logged assert False, "Rotated anchored data failed to load" source_processor = EYAMLProcessor( quiet_logger, yaml_anchored_data, privatekey=old_eyaml_keys[0], publickey=old_eyaml_keys[1]) for node in source_processor.get_eyaml_values( '/block', True ): assert unwrap_node_coords(node) == 'This is a test value.' rotated_processor = EYAMLProcessor( quiet_logger, yaml_rotated_data, privatekey=new_eyaml_keys[0], publickey=new_eyaml_keys[1]) for node in rotated_processor.get_eyaml_values( '/block', True ): assert unwrap_node_coords(node) == 'This is a test value.'