que votre exemple est invalide est uniquement parce que vous avez choisi un caractère réservé pour commencer votre avec scalaires. Si vous remplacez le *
avec un autre caractère non réservé (j'ai tendance à utiliser des caractères non-ASCII pour que, comme ils sont rarement utilisés dans le cadre de certaines spécifications), vous vous retrouvez avec YAML parfaitement légal:
paths:
root: /path/to/root/
patha: ♦root♦ + a
pathb: ♦root♦ + b
pathc: ♦root♦ + c
Cela va charger dans la représentation standard pour les mappages dans la langue que votre analyseur utilise et ne développe rien magiquement.
Pour ce faire utilisez un type d'objet par défaut localement comme dans le programme Python suivant:
# coding: utf-8
from __future__ import print_function
import ruamel.yaml as yaml
class Paths:
def __init__(self):
self.d = {}
def __repr__(self):
return repr(self.d).replace('ordereddict', 'Paths')
@staticmethod
def __yaml_in__(loader, data):
result = Paths()
loader.construct_mapping(data, result.d)
return result
@staticmethod
def __yaml_out__(dumper, self):
return dumper.represent_mapping('!Paths', self.d)
def __getitem__(self, key):
res = self.d[key]
return self.expand(res)
def expand(self, res):
try:
before, rest = res.split(u'♦', 1)
kw, rest = rest.split(u'♦ +', 1)
rest = rest.lstrip() # strip any spaces after "+"
# the lookup will throw the correct keyerror if kw is not found
# recursive call expand() on the tail if there are multiple
# parts to replace
return before + self.d[kw] + self.expand(rest)
except ValueError:
return res
yaml_str = """\
paths: !Paths
root: /path/to/root/
patha: ♦root♦ + a
pathb: ♦root♦ + b
pathc: ♦root♦ + c
"""
loader = yaml.RoundTripLoader
loader.add_constructor('!Paths', Paths.__yaml_in__)
paths = yaml.load(yaml_str, Loader=yaml.RoundTripLoader)['paths']
for k in ['root', 'pathc']:
print(u'{} -> {}'.format(k, paths[k]))
qui imprimera:
root -> /path/to/root/
pathc -> /path/to/root/c
L'expansion se fait à la volée et les poignées définitions imbriquées, mais vous doivent faire attention à ne pas invoquer la récursion infinie.
En spécifiant le dumper, vous pouvez vider le YAML d'origine à partir des données chargées, à cause de la sur la volée extension:
dumper = yaml.RoundTripDumper
dumper.add_representer(Paths, Paths.__yaml_out__)
print(yaml.dump(paths, Dumper=dumper, allow_unicode=True))
cela va changer l'ordre des clés de la cartographie. Si tel est un problème que vous avez à faire self.d
un CommentedMap
(importé de ruamel.yaml.comments.py
)
** Voir aussi: ** https://stackoverflow.com/a/41620747/42223 – dreftymac