2012-12-22 6 views
6

Ich benutze YAML für einen Computer und ein vom Benutzer editierbares und lesbares Eingabeformat für einen Simulator. Für die menschliche Lesbarkeit sind einige Teile des Inputs hauptsächlich dazu geeignet, den Stil zu blockieren, während der Flow-Stil anderen besser passt.Angeben von Stilen für Teile eines PyYAML-Speicherauszugs

Der Standardwert für PyYAML ist die Verwendung von Blockstilen überall dort, wo es verschachtelte Maps oder Sequenzen und Fließkommas gibt. * default_flow_style * erlaubt die Auswahl von All-Flow-Style oder All-Block-Style.

Aber ich möchte Ausgabedateien, um mehr von der Form

bonds: 
- { strength: 2.0 } 
- ... 
tiles: 
- { color: red, edges: [1, 0, 0, 1], stoic: 0.1} 
- ... 
args: 
    block: 2 
    Gse: 9.4 

Wie man sehen kann, dies folgt nicht ein einheitliches Muster für Stile im gesamten, und stattdessen ändert sich in Abhängigkeit von dem Teil der Datei . Im Wesentlichen möchte ich in der Lage sein, festzulegen, dass alle Werte in einigen Blockstyle-Sequenzen im Flow-Stil sind. Gibt es einen Weg, diese Art von Kontrolle über das Dumping zu erreichen? Die Möglichkeit, das Mapping der obersten Ebene in einer bestimmten Reihenfolge abzulegen, während diese Reihenfolge nicht erforderlich ist (z. B. omap), wäre ebenfalls gut für die Lesbarkeit.

Antwort

11

Es stellt sich heraus, dass dies getan werden kann, indem Unterklassen mit Repräsentanten für jeden Artikel, die ich nicht default_flow_style folgen will, und dann konvertieren alle notwendigen zu denen vor dem Dumping. In diesem Fall, das heißt, ich bekomme so etwas wie:

class blockseq(dict): pass 
def blockseq_rep(dumper, data): 
    return dumper.represent_mapping(u'tag:yaml.org,2002:map', data, flow_style=False) 

class flowmap(dict): pass 
def flowmap_rep(dumper, data): 
    return dumper.represent_mapping(u'tag:yaml.org,2002:map', data, flow_style=True) 

yaml.add_representer(blockseq, blockseq_rep) 
yaml.add_representer(flowmap, flowmap_rep) 

def dump(st): 
    st['tiles'] = [ flowmap(x) for x in st['tiles'] ] 
    st['bonds'] = [ flowmap(x) for x in st['bonds'] ] 
    if 'xgrowargs' in st.keys(): st['xgrowargs'] = blockseq(st['xgrowargs']) 
    return yaml.dump(st) 

Ärgerlicher, desto leichter zu bedien dumper.represent_list und dumper.represent_dict erlauben nicht flow_style angegeben werden, also habe ich den Tag angeben, aber das System funktioniert.

+0

Ist Ihr Kommentar immer noch aktuell über 'dumper.represent_sequence' und' dumper.represent_dict' ohne eine Option flow_style? siehe http://pyyaml.org/wiki/PyYAMLDocumentation#Dumper – Hotschke

+0

Eigentlich versuche ich deine 'flowmap' auf eine Sequenz anzuwenden:' - Kanten: \ n - [1,2] \ n - [2, 1, [1 , 0]] '. Ich hätte gerne jede Kante in einer einzelnen separaten Zeile (wie mit '\ n' bezeichnet). Momentan sieht es so aus: '- Kanten: \ n - [1,2] \ n - 1 \ n - 2 \ n - [1, 0]' – Hotschke

+0

Ja, mein Kommentar ist immer noch gültig; 'represent_mapping' hat es, aber die anderen beiden nicht; Sie sind wahrscheinlich nur Wrapper für 'represent_mapping'. Was Sie tun, ist Flowmap nicht was Sie wollen. Sie eine Sequenz (unter Kanten :), die Sie haben möchten, flow_style = True, kein Mapping. – cge