Сохранить SQL в YAML как есть

Я хочу сохранить SQL в файл YAML в своем собственном формате, как показано ниже:

(1)   
sql: SELECT DISTINCT p.id_product, 
                     p.price AS price, 
                     sp.reduction AS discount
       FROM ....

Я использую следующие настройки YAML

yaml.safe_dump(app_config,
               stream,
               indent=4,
               default_flow_style=False,
               encoding='utf-8',
               allow_unicode=True)

однако я получил «классический» уродливый вывод YAML

(2)
sql: SELECT DISTINCT p.id_product, p.price AS price, sp.reduction AS discount, sp.reduction_type
    AS discount_type, pl.description_short AS description FROM ....

Есть ли способ добиться результата №1?

PS. repr(config) равно:

{'mapping': {'/*ID_LANG*/': 'AND pl.id_lang IN (/*VALUE*/)', '/*REFERENCE*/': "AND p.reference LIKE '%/*VALUE*/%'", }, 'sql': 'SELECT DISTINCT p.id_product, p.price AS price, sp.reduction AS discount, sp.reduction_type AS discount_type, pl.description_short AS description, pl.name AS name, i.id_image as image, p.reference AS model, m.name AS manufacturer, pl.available_now AS stock_status FROM /*PREFIX*/product p LEFT JOIN /*PREFIX*/product_lang pl ON (p.id_product = pl.id_product) LEFT JOIN /*PREFIX*/manufacturer m ON (m.id_manufacturer = p.id_manufacturer) LEFT JOIN /*PREFIX*/image i ON (i.id_product = p.id_product) LEFT JOIN /*PREFIX*/specific_price sp ON (sp.id_product = p.id_product) LEFT JOIN /*PREFIX*/category pc ON p.id_category_default = pc.id_category WHERE i.cover = 1 /*WHERE*/'}

person SpanishBoy    schedule 20.05.2015    source источник
comment
можем ли мы предположить, что {1) и (2) не являются частью вывода YAML? Можете ли вы включить вывод repr(app_config)?   -  person Anthon    schedule 20.05.2015
comment
{1} и {2} на самом деле являются выходными данными YAML.   -  person SpanishBoy    schedule 21.05.2015
comment
Я должен был это процитировать. Строка (1) соотв. (2) которые находятся в блоке разметки кода (выше sql), которые не являются частью блока YAML. Я пытался поместить это за пределы блока, но тогда вы получаете много пустого пространства.   -  person Anthon    schedule 21.05.2015


Ответы (1)


Если ваш входной формат представляет собой какой-то неформатированный SQL (без новых строк и отступов), как вы, кажется, взяли из вывода (2), вы никогда автоматически не получите хороший вывод:

import yaml

sql = ("SELECT DISTINCT p.id_product, "
                      "p.price AS price, "
                      "sp.reduction AS discount, "
                      "sp.reduction_type AS discount_type, "
                      "pl.description_short AS description "
                      "FROM ....")
app_config = dict(sql=sql)
print yaml.dump(app_config)

дам тебе:

{sql: 'SELECT DISTINCT p.id_product, p.price AS price, sp.reduction AS discount, sp.reduction_type
    AS discount_type, pl.description_short AS description FROM ....'}

как вы узнали. Вы можете попробовать вручную отформатировать строку с новыми строками и отступами.

app_config = dict(sql="""\
SELECT DISTINCT p.id_product,
                p.price AS price,
                sp.reduction AS discount,
                sp.reduction_type AS discount_type,
                pl.description_short AS description
    FROM ....""")
print yaml.dump(app_config)

но результат не намного лучше:

{sql: "SELECT DISTINCT p.id_product,\n                p.price AS price,\n        \
    \        sp.reduction AS discount,\n                sp.reduction_type AS discount_type,\n\
    \                pl.description_short AS description\n    FROM ...."}


Я предлагаю вам использовать другой подход и установить средство форматирования sql, например sqlparse или format-sql в сочетании с ruamel.yaml (я являюсь автором этой расширенной версии PyYAML), которая поддерживает циклический обход многострочных литеральных строк. С небольшой помощью его также можно использовать для создания правильного и лучшего (если не лучшего) вывода YAML.

Ты можешь сделать:

import ruamel.yaml
from ruamel.yaml.scalarstring import PreservedScalarString
import sqlparse

sql = ("SELECT DISTINCT p.id_product, "
       "p.price AS price, "
       "sp.reduction AS discount, "
       "sp.reduction_type AS discount_type, "
       "pl.description_short AS description "
       "FROM ....")
fsql = sqlparse.format(sql, reindent=True, keyword_case="upper").encode('utf-8')

app_config = dict(sql=PreservedScalarString(fsql))
print ruamel.yaml.dump(app_config, Dumper=ruamel.yaml.RoundTripDumper)

и получите литеральный скаляр YAML с сохраненными символами новой строки:

sql: |-
  SELECT DISTINCT p.id_product,
                  p.price AS price,
                  sp.reduction AS discount,
                  sp.reduction_type AS discount_type,
                  pl.description_short AS description
  FROM ....

Надеюсь, достаточно близко к тому, что вы хотели.

person Anthon    schedule 20.05.2015