Подтвердить что ты не робот

Более сложное наследование в YAML?

YAML имеет наследование. Самый ясный пример, который я когда-либо видел, здесь: http://blog.101ideas.cz/posts/dry-your-yaml-files.html

Мне нужно что-то более сложное: мне нужно переопределить свойство объекта объекта. Вот пример:

database: &default
  server:
    ip: 192.168.1.5
    port: 2000
  db_name: test
  user: 
    name: root
    password: root

# database foo differs from default by only its port and user password
foo_database:
  <<: *default
  server:
    port: 2001
  db_name: foo
  user:
    password: foo_root

Я хочу получить этот результат:

foo_database.server.ip -> 192.168.1.5
foo_database.server.port -> 2001
foo_database.db_name -> foo
foo_database.user.name -> root
foo_database.user.password -> foo_root

Но если вы так заявляете, вы получите эти свойства некорректными (в соответствии с ожидаемыми значениями):

foo_database.server.ip -> will be None
foo_database.user.name -> will be None

потому что новый объект "server" имеет только свойство "port" и переопределяет весь старый "серверный" объект.

Как мне получить наследование, которое я хочу достичь?

4b9b3361

Ответ 1

К сожалению, вы не можете получить такое "наследование", которое хотите достичь, потому что YAML "наследование" больше похоже на форму "слияния хэшей".

Развернув конфигурацию в точке, в которой вы используете псевдоним *default, у вас есть:

foo_database:
  server:
    ip: 192.168.1.5
    port: 2000
  db_name: test
  user: 
    name: root
    password: root

Если вы используете хэши с теми же ключами после этого, они полностью перезапишут хеши, объявленные ранее, оставив вас (извините за форматирование):

foo_database:

  server:
    ip: 192.168.1.5
    port: 2000
  db_name: test
  user: 
   name: root
   password: root  

Забастовкa >

  server:
    port: 2001
  db_name: foo
  user:
    password: foo_root

Итак, в вашем случае, похоже, что, поскольку конфигурация не совсем то же самое, DRYing вашей конфигурации с использованием якорей и псевдонимов, вероятно, не подходит.

Дополнительные ссылки по этому вопросу ниже:

Изменить

Если вы действительно этого хотели, я думаю, что вы могли бы перенастроить свой YAML, как показано ниже, чтобы получить именно то, что вы хотите, но в вашем случае я бы сказал, что дополнительная обфускация не стоит того:

server_defaults: &server_defaults
  ip: 192.168.1.5
  port: 2000

user_defaults: &user_defaults
  name: root
  password: root

database: &default
  server:
    <<: *server_defaults
  db_name: test
  user: 
    <<: *user_defaults

foo_database:
  <<: *default
  server:
    <<: *server_defaults
    port: 2001
  db_name: foo
  user:
    <<: *user_defaults
    password: foo_root

Ответ 2

Как насчет этого? Используйте несколько якорей.

database: &default
  server: &server
    ip: 192.168.1.5
    port: 2000
  db_name: test
  user: &user
    name: root
    password: root

foo_database:
  <<: *default
  server:
    << : *server
    port: 2001
  db_name: foo
  user:
    << : *user
    password: foo_root

Это просто небольшая дополнительная работа, и немного сложнее читать, чем если бы вы захотели были встроены в YAML, как вы предположили (я думал, что это тоже сработает). Но в целом неплохо.