Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

pretty output with pyyaml

I have a python project where I'd like to use YAML (pyYaml 3.11), particularly because it is "pretty" and easy for users to edit in a text editor if and when necessary. My problem, though, is if I bring the YAML into a python application (as I will need to) and edit the contents (as I will need to) then writing the new document is typically not quite as pretty as what I started with.

The pyyaml documentation is pretty poor - does not even document the parameters to the dump function. I found http://dpinte.wordpress.com/2008/10/31/pyaml-dump-option/. However, I'm still missing the information I need. (I started to look at the source, but it doesn't seem the most inviting. If I don't get the solution here, then that's my only recourse.)

I start with a document that looks like this:

- color green :
     inputs :
        - port thing :
            widget-hint : filename
            widget-help : Select a filename
        - port target_path : 
            widget-hint : path
            value : 'thing' 
     outputs:
        - port value:
             widget-hint : string
     text : |
            I'm lost and I'm found
            and I'm hungry like the wolf.

After loading into python (yaml.safe_load( s )), I try a couple ways of dumping it out:

>>> print yaml.dump( d3, default_flow_style=False, default_style='' )
- color green:
    inputs:
    - port thing:
        widget-help: Select a filename
        widget-hint: filename
    - port target_path:
        value: thing
        widget-hint: path
    outputs:
    - port value:
        widget-hint: string
    text: 'I''m lost and I''m found

      and I''m hungry like the wolf.

      '
>>> print yaml.dump( d3, default_flow_style=False, default_style='|' )
- "color green":
    "inputs":
    - "port thing":
        "widget-help": |-
          Select a filename
        "widget-hint": |-
          filename
    - "port target_path":
        "value": |-
          thing
        "widget-hint": |-
          path
    "outputs":
    - "port value":
        "widget-hint": |-
          string
    "text": |
      I'm lost and I'm found
      and I'm hungry like the wolf.

Ideally, I would like "short strings" to not use quotes, as in the first result. But I would like multi-line strings to be written as blocks, as with the second result. I guess fundamentally, I'm trying to minimize an explosion of unnecessary quotes in the file which I perceive would make it much more annoying to edit in a text editor.

Does anyone have any experience with this?

like image 230
Mayur Patel Avatar asked Jun 25 '14 20:06

Mayur Patel


People also ask

What is PyYAML used for?

PyYAML is a YAML parser and emitter for Python. Using the PyYAML module, we can perform various actions such as reading and writing complex configuration YAML files, serializing and persisting YMAL data. Use it to convert the YAML file into a Python dictionary.

Is PyYAML same as YAML?

YAML is a data serialization format designed for human readability and interaction with scripting languages. PyYAML is a YAML parser and emitter for Python. PyYAML features a complete YAML 1.1 parser, Unicode support, pickle support, capable extension API, and sensible error messages.

Is PyYAML included in Python?

PyYAML is a YAML parser and emitter for the Python programming language.

What does YAML dump return?

dump will write the produced YAML document into the file. Otherwise, yaml. dump returns the produced document.

What is PyYaml module in Python?

PyYAML Module PyYAML is a YAML parser and emitter for Python. Using the PyYAML module, we can perform various actions such as reading and writing complex configuration YAML files, serializing and persisting YMAL data. Use it to convert the YAML file into a Python dictionary.

How to teach YAML in PyYaml?

There is a way to teach PyYAML that any untagged plain scalar which looks like XdY has the implicit tag !dice. Use add_implicit_resolver: A good introduction to the YAML syntax is Chapter 2 of the YAML specification.

How to install PyYaml on Linux?

There are two ways to install it on your machine. The following are the ways: PyYAML is available on pypi.org, so you can install it using the pip command. Open the command prompt and run the below pip command to install the PyYAML module

How does PyYaml choose the style of a collection?

(see #18, #24)? It’s a correct output despite the fact that the style of the nested mapping is different. By default, PyYAML chooses the style of a collection depending on whether it has nested collections. If a collection has nested collections, it will be assigned the block style. Otherwise it will have the flow style.


2 Answers

Try the pyaml pretty printer. It gets closer, though it does put quotes around short strings with spaces in them:

>>> print pyaml.dump(d3)
- 'color green':
    inputs:
      - 'port thing':
          widget-help: 'Select a filename'
          widget-hint: filename
      - 'port target_path':
          value: thing
          widget-hint: path
    outputs:
      - 'port value':
          widget-hint: string
    text: |
      I'm lost and I'm found
      and I'm hungry like the wolf.
like image 128
Aryeh Leib Taurog Avatar answered Sep 17 '22 14:09

Aryeh Leib Taurog


If you can use ruamel.yaml (disclaimer: I am the author of this enhanced version of PyYAML) you can do:

import ruamel.yaml

yaml_str = """\
- color green :
     inputs :
        - port thing :
            widget-hint : filename
            widget-help : Select a filename
        - port target_path :
            widget-hint : path
            value : 'thing'
     outputs:
        - port value:
             widget-hint : string
     text : |
            I'm lost and I'm found
            and I'm hungry like the wolf.
"""

data = ruamel.yaml.round_trip_load(yaml_str)
res = ""
for line in ruamel.yaml.round_trip_dump(data, indent=5, block_seq_indent=3).splitlines(True):
    res += line[3:]
print(res)

you get:

- color green:
       inputs:
          - port thing:
                 widget-hint: filename
                 widget-help: Select a filename
          - port target_path:
                 widget-hint: path
                 value: thing
       outputs:
          - port value:
                 widget-hint: string
       text: |
            I'm lost and I'm found
            and I'm hungry like the wolf.

Not exactly what you did start out with (but after this round-trip it is stable). With more recent versions of ruamel.yaml you can set both the indent and the relative indent of a sequence - within that indent. The latter however also influences your top-level sequence, hence the post processing.

Important (to me) things that are preserved: comments, anchors, mapping merges, and literal scalars ( multi-line using |)

like image 24
Anthon Avatar answered Sep 18 '22 14:09

Anthon