Closed tsinggggg closed 2 years ago
Please open a proper bug report. I can't see where the failure is or test your issue with this little information.
Having said that, I'm not sure your expectations are quite right. The wrapper types you speak of are the native ruamel.yaml types and are required by ruamel.yaml to properly round-trip the data<->stream. What issue are you really having?
Thanks for the response. I am not sure if this is a bug, or I am abusing the package.
Under this setup, I was trying to create a Processor, add something to the underlying data, then serialize it.
OS: MacOS 12.3.1 (21E258)
Python 3.9.12
yamlpath 3.6.4
ruamel.yaml 0.17.17
With the script
from types import SimpleNamespace
from ruamel.yaml import YAML
from yamlpath.wrappers import ConsolePrinter
from yamlpath import Processor
from yamlpath.enums.yamlvalueformats import YAMLValueFormats
if __name__ == '__main__':
log = ConsolePrinter(
SimpleNamespace(quiet=True, verbose=False, debug=False)
)
config = {"key1": [1, 2, 3],
"key2": {
"key3": "value1",
"key4": "value2",
}
}
processor = Processor(log, config)
processor.set_value("x", "asdf", value_format=YAMLValueFormats.DEFAULT)
with open("test.yml", "w", encoding="utf-8") as cfgyaml:
yaml = YAML(typ="safe")
yaml.default_flow_style = False
yaml.dump(config, cfgyaml)
Do I mistakenly expect this to work? currently it throws an error ruamel.yaml.representer.RepresenterError: cannot represent an object
You're forming a bit of a mixed bag by using yamlpath classes against bare ruamel.yaml classes. Let yamlpath handle the boilerplate ruamel.yaml setup for you and this cleans right up:
from types import SimpleNamespace
from yamlpath.wrappers import ConsolePrinter
from yamlpath import Processor
from yamlpath.enums.yamlvalueformats import YAMLValueFormats
from yamlpath.common import Parsers
if __name__ == '__main__':
log = ConsolePrinter(
SimpleNamespace(quiet=True, verbose=False, debug=False)
)
config = {"key1": [1, 2, 3],
"key2": {
"key3": "value1",
"key4": "value2",
}
}
processor = Processor(log, config)
processor.set_value("x", "asdf", value_format=YAMLValueFormats.DEFAULT)
with open("test.yml", "w", encoding="utf-8") as cfgyaml:
yaml = Parsers.get_yaml_editor()
yaml.dump(config, cfgyaml)
$ ls -1
180.py
$ python ./180.py
$ ls -1
180.py
test.yml
$ cat ./test.yml
---
key1:
- 1
- 2
- 3
key2:
key3: value1
key4: value2
x: asdf
I'm closing this out as a non-issue. There is abundant documentation about using the yamlpath helpers:
Thanks for the suggestion!
A follow up question, under the same setting, list(processor.get_nodes("x"))[0].node
returns a PlainScalarString
, is this the intended way to do it? or is there a way I can query the path "x"
and returns a primitive string?
https://sourceforge.net/p/ruamel-yaml/code/ci/default/tree/scalarstring.py is a just a primitive str
with some dressings necessary for ruamel.yaml to properly round-trip YAML data while preserving all formatting, comments, and so on. Operations you'd normally expect to run with or against a primitive str
will work against the ruamel.yaml string extensions. If you absolutely had to strip off the extra dressings anyway, use str()
:
>>> import ruamel.yaml
>>> ys = ruamel.yaml.scalarstring.PlainScalarString("abc")
>>> ys
'abc'
>>> type(ys)
<class 'ruamel.yaml.scalarstring.PlainScalarString'>
>>> isinstance(ys, str)
True
>>> type(str(ys))
<class 'str'>
When you add any value to a
Processor
, the added value will get wrapped with a data type likePlainScalarString
.Is there a way around this and keep the original data type?
I was kind of hacking it like
The current implementation has 2 disadvantages this way: