Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Saving config files with !new tags #24

Open
egaznep opened this issue Nov 26, 2023 · 2 comments
Open

Saving config files with !new tags #24

egaznep opened this issue Nov 26, 2023 · 2 comments
Assignees

Comments

@egaznep
Copy link

egaznep commented Nov 26, 2023

Hello,

I have the following code (a MWE - minimum working example), where I want to dump a config with a !new instatiation.

yaml_string = """
foo: !new:collections.Counter
  a: 4
bar: !ref <foo>
baz: !copy <foo>
"""
loaded_yaml = load_hyperpyyaml(yaml_string)
from hyperpyyaml import dump_hyperpyyaml
# Importing the StringIO module.
from io import StringIO

dump_hyperpyyaml(loaded_yaml, StringIO())

This fails with the following

RepresenterError                          Traceback (most recent call last)

[<ipython-input-6-c8804319bfb8>](https://localhost:8080/#) in <cell line: 14>()
     12 from io import StringIO
     13 
---> 14 dump_hyperpyyaml(loaded_yaml, StringIO())

9 frames

[/usr/local/lib/python3.10/dist-packages/ruamel/yaml/representer.py](https://localhost:8080/#) in represent_undefined(self, data)
    343 
    344     def represent_undefined(self, data: Any) -> None:
--> 345         raise RepresenterError(f'cannot represent an object: {data!s}')
    346 
    347 

RepresenterError: cannot represent an object: Counter({'a': 4})

Neither the docs, nor the given Colab notebook contains an example of dumping with the !new tag. How could this be done?

@pplantinga
Copy link
Collaborator

tl;dr this is not possible with the current way this is structured.

Longer answer:

There's no general way to extract the arguments used to construct an object. On the other hand, if you wanted to use it for specific cases, this would have to be done with something like the add_representer in the current dump_hyperpyyaml where the to_yaml function tells the representer how to convert the class to a string:

def dump_hyperpyyaml(yaml_tree, output_stream, *args, **kwargs):
    ruamel_yaml = ruamel.yaml.YAML()
    ruamel_yaml.representer.add_representer(RefTag, RefTag.to_yaml)
    ruamel_yaml.representer.add_representer(Placeholder, Placeholder.to_yaml)
    ruamel_yaml.dump(yaml_tree, output_stream, *args, **kwargs)

I suppose one simple change that might allow a user to do this is to do something like:

def dump_hyperpyyaml(yaml_tree, output_stream, represented_classes=[RefTag, Placeholder], *args, **kwargs):
    ruamel_yaml = ruamel.yaml.YAML()
    for represented_class in represented_classes:
        ruamel_yaml.representer.add_representer(represented_class, represented_class.to_yaml)
    ruamel_yaml.dump(yaml_tree, output_stream, *args, **kwargs)

Is this something that would likely work for your use case?

@pplantinga pplantinga self-assigned this Dec 13, 2023
@egaznep
Copy link
Author

egaznep commented Dec 14, 2023

I understand. Ideally, as a user I would appreciate something more towards how hydra manages to do this - not requiring extra effort from the users. I did not study how that works though - could be requiring some changes to how hyperpyyaml functions. For the time being, I just want to dump the configuration for certain speech processing pipeline segments - so I can get away with making a base class dumpable (according to your first snippet) and everything else can inherit. Thank you for the reply 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants