omry / omegaconf

Flexible Python configuration system. The last one you will ever need.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Work with dots in keynames

MatteoVoges opened this issue · comments

Is your feature request related to a problem? Please describe.
Is there a way to work with dots in keys, where the dots are part of the key and not function as path delimiter?

Describe the solution you'd like
Example:

labels:
  app.kubernetes.io/name: mylabel

reference: ${labels.app.kubernetes.io/name}

The goal would be to have referenceresolved as mylabel.

I know that this is a tricky one, because the dot is the path delimiter, but I am thinking of a modification of the config creation like in the function OmegaConf.from_dotlist(), so that in fact the DictConfig
{"labels": {"app": {"kubernetes": {"io/name": "mylabel"}}}}
gets created and the interpolation can get resolved correctly.

OmegaConf does not entirely prevent using dots in key names: if you load your config, you should be able to access cfg.labels["app.kubernetes.io/name"]. This also means we can't automatically do what you're suggesting (this would break existing code relying on this feature).

An ugly workaround is to do something like:

labels:
  app.kubernetes.io/name: ${._app_kubernetes_io_name}
  _app_kubernetes_io_name: mylabel

reference: ${labels._app_kubernetes_io_name}

but it's unlikely to be what you're looking for.

Your best bet is probably to figure out how to change the yaml yourself (possibly in an automated way) so that it becomes

labels:
  app:
    kubernetes:
      io/name: mylabel

reference: ${labels.app.kubernetes.io/name}

(or, write your own loader for your yaml file, generate the dict you want to use and pass it to OmegaConf.create())

Thank you for your answer. Do you have any ideas in mind how to achieve this behavior with a custom resolver? Maybe if we pass a list of all real parts of the key (i.e. labels, app.kubernetes.io/name) and access them with your proposed method using [].

Do you have any ideas in mind how to achieve this behavior with a custom resolver?

Hmm, I think you can probably achieve something that would look like either

labels:
  app.kubernetes.io/name: some_name

_labels: ${my_custom_resolver: ${labels}}  # convert it to DictConfig without dots in key names

reference: ${_labels.app_kubernetes_io/name}

or

labels:
  app:
    kubernetes:
      io/name: some_name

_labels: ${my_custom_resolver: ${labels}}  # convert it to DictConfig with dots in key names

reference: ${labels.app_kubernetes_io/name}

This could be achieved with a custom resolver that returns a DictConfig (one example here: https://github.com/omry/omegaconf/blob/master/omegaconf/resolvers/oc/__init__.py#L14)

(the second example is in case you need to recover the "original" format -- I'm not sure if it matters in your use case)

Maybe if we pass a list of all real parts of the key (i.e. labels, app.kubernetes.io/name) and access them with your proposed method using []

I'm not sure I understand what you have in mind here.

Good idea with converting the key into a nested config, especially, because I could use from_dotlist() in the resolver, right?

I'm not sure I understand what you have in mind here.

def access_key_with_dots(parts*):

    reference = config # get the config (idk, like in oc.select)
    for part in parts:
        reference = reference[part] # get element by whole key with brackets

    return reference

And now I could use the resolver like:

reference: ${access_key_with_dots:labels,app.kubernetes.io/name} # should get resolved into mylabel

Alternatively we could pass the last key without a dot into the resolver and access it directly:

def access_key_with_dots(config: DictConfig, key_with_dots: str):
    return config[key_with_dots]

Usage:

reference: ${access_key_with_dots:${labels},app.kubernetes.io/name}

Ah, yes, you could indeed write a custom version of oc.select to achieve what you want!

Thanks again for your help and ideas. For me, the workaround using the resolver is fine, so I would close the issue.