4

I am trying generate a YAML file from Python object in which I have some literal string attribute pattern = "^[0-9]+$" to add to equally named node pattern as folder block.

Code

So far I have progressed till below code

import yaml
class MyDumper(yaml.Dumper):
    def increase_indent(self, flow=False, indentless=False):
        return super(MyDumper, self).increase_indent(flow, False)


source = {'row_filters':{'NONE':{'filter_sql_expr': True}},
          'rule_dimensions': ['completeness','conformance'],
          'rules': {'VALID_CUSTOMER_ID': {'rule_type': 'REGEX', 'dimension': 'accuracy', 'params': {'pattern': "^[0-9]+$"}}}}    

print(yaml.dump(source, Dumper=MyDumper, default_flow_style=False,sort_keys=False,indent=2,allow_unicode=True))

Actual YAML Output

row_filters:
  NONE:
    filter_sql_expr: True
rule_dimensions:
  - completeness
  - conformance
rules:
  VALID_CUSTOMER_ID:
    rule_type: REGEX
    dimension: accuracy
    params:
      pattern: ^[0-9]+$

Expected YAML output

row_filters:
 NONE:
   filter_sql_expr: |-
      True
rule_dimensions:
  - completeness
  - conformance
rules:
  VALID_CUSTOMER_ID:
    rule_type: REGEX
    dimension: accuracy
    params:
      pattern: |-
        ^[0-9]+$

Wanted

I need to add |- for multi-line block with block chomping indicator - in order to add strings as block literals.

Questions

  1. How to force the adding the string in block-style with |- ?
  2. How to add the method to my my Dumper class for conversion ?
hc_dev
  • 8,389
  • 1
  • 26
  • 38
RoxaneFelton
  • 129
  • 7

1 Answers1

1

You can use Representer.add_representer() to show block literals, more details here

class folded_str(str): pass

class literal_str(str): pass

class literal_unicode(str): pass

def change_style(style, representer):
    def new_representer(dumper, data):
        scalar = representer(dumper, data)
        scalar.style = style
        return scalar
    return new_representer

import yaml
from yaml.representer import SafeRepresenter

yaml.add_representer(literal_str, represent_literal_str)

fse = True
ptrn = "^[0-9]+$"

source = {'row_filters':{'NONE':{'filter_sql_expr': literal_str(fse)}},
          'rule_dimensions': ['completeness','conformance'],
          'rules': {'VALID_CUSTOMER_ID': {'rule_type': 'REGEX', 'dimension': 'accuracy', 'params': {'pattern':literal_str(ptrn)}}}}

print(yaml.dump(source))

Output

row_filters:
  NONE:
    filter_sql_expr: |-
      True
rule_dimensions:
- completeness
- conformance
rules:
  VALID_CUSTOMER_ID:
    dimension: accuracy
    params:
      pattern: |-
        ^[0-9]+$
    rule_type: REGEX
Prakash Dahal
  • 4,388
  • 2
  • 11
  • 25
  • I have tried this but the problem is the source dictionary is getting created from file and on updating ptrn to literal_str(ptrn) the value is coming in String format "literal_str(ptrn)" due to which it causing an issue in calling the function literal_str. Is there any other approach which can be invoked from My Dumper Class – RoxaneFelton Dec 29 '22 at 20:49
  • can we add this in the My Dumper Class. As although your approach is fine I am looking for an alternative solution which will fit my scenario asI have to create the Source dictionary and on creating it takes all values as Strings and literal_str will not get executed and will be treated as String – RoxaneFelton Dec 29 '22 at 20:55
  • For that string, can you use `eval` method, like `eval('literal_str(ptrn)')` – Prakash Dahal Dec 30 '22 at 17:18