Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PyYAML dumping boolean

I am loading a yaml True/False item(example below) from a YAML file.

gzip: False

This is correctly interpreted in a Jinja2 template as boolean True.

The same YAML file is being read by another script, passed over as a python CGI form data and eventually written to the YAML file using

with open(myyaml, 'w') as yaml_file:
    yaml_file.write(yaml.dump(dict, default_flow_style=False)) 

The issue is that this then writes the True/False with a single quote

gzip: 'False'

which causes the jinja2 template to not interpret the value as boolean and always sets value as true in

{{ if gzip }}

Is there a way to dump the YAML file with True/False values that are treated as boolean ( I mean without the quotes ).

like image 276
Anoop P Alias Avatar asked Nov 03 '16 06:11

Anoop P Alias


People also ask

Does YAML support Boolean?

Boolean values can be represented in YAML using the keywords like true and false or Yes and No .

What does PyYAML do?

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.

Can PyYAML parse JSON?

It is often used for configuration files, but can also be used for data exchange. The most used python YAML parser is PyYAML, a library that allows you to load, parse, and write YAML, much like Python's JSON library helps you to work with JSON.

What does YAML dump return?

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


1 Answers

.dump() just dumps the data that it gets and it must have gotten a string instead of boolean as value for the key gzip. Since that string value, if dumped unquoted can be misinterpreted as a boolean it gets quoted.

Since you get your material from a CGI form any value True or False will be a string. Before dumping your data, you explicitly have to convert these values you got from CGI to booleans.

You can walk over your dictionary and do something generic processing before you dump:

import sys
import yaml

# simulating getting string type values from CGI
data = dict(gzip='False', intval="1", strval="abc") 

for k in data:
    v = data[k]
    try:
        v = int(v)
        data[k] = v
    except ValueError:
        vl = v.lower()
        if vl == 'false':
            data[k] = False
        elif vl == 'true':
            data[k] = True

yaml.safe_dump(data, sys.stdout, default_flow_style=False)

gives:

gzip: false
intval: 1
strval: abc

Please note that abc is not quoted, because it cannot be interpreted as anything else but a string. The above of course also converts strings 'True' or 'False' that would have to stay strings. If that is not what you want, you have to select conversion based on the key.

There are two other major problems with your two lines of Python:

with open(myyaml, 'w') as yaml_file:
    yaml_file.write(yaml.dump(dict, default_flow_style=False)) 
  1. You should never use a Python keyword (dict) as a variable name, that is just asking for trouble later on in your code.
  2. yaml.dump() dumps data to a stream. It has a facility that if you don't specify the stream where things have to go to, the output is written to an internal stream object, from which the final value is returned. You should not abuse this, to then write this returned value to the yaml_file. Instead do:

    with open(myyaml, 'w') as yaml_file:
        yaml.dump(dict, yaml_file, default_flow_style=False))
    

    Your way is inefficient (apart from showing lack of understanding).

like image 156
Anthon Avatar answered Sep 17 '22 00:09

Anthon