Проверка наличия повторяющегося поля в сообщении protobuff

#python #unit-testing #protocol-buffers

#python #модульное тестирование #протокол-буферы

Вопрос:

У меня есть сообщение Google protobuf:

 message Foo {
  required int bar = 1;
}
  

Я знаю, что для проверки полей сообщения мы можем использовать:

 foo.bar = 1
assert foo.HasField("bar")
  

Однако «HasField» не работает для повторяющихся типов полей.
Как проверить наличие поля для «повторяющегося типа» полей?

 message Foo {
  repeated int bar = 1;
}
  

Комментарии:

1. Похоже, никто действительно не понял ваш вопрос. Вы хотели указать, не было ли предоставлено повторяющееся поле, или если оно было явно установлено пустым. Я пытаюсь добиться того же… вы когда-нибудь находили решение?

Ответ №1:

Вы могли бы попытаться проверить длину повторяющегося поля:

 assert len(foo.bar) == 0
  

Комментарии:

1. но это только дает мне знать, что поле добавлено, но не какое это поле.

2. Да, вы должны знать, какое поле у вас есть в вашем прототипе. Gje

3. Метод hasfield в основном используется для проверки того, установлено ли поле с некоторым значением

4. но hasfield не работает для повторяющихся полей

5. Да, именно поэтому вы можете вместо этого протестировать длину

Ответ №2:

Способ обойти это — включить повторяющееся поле в его собственное сообщение.

 message Foo {
  message Bars {
    repeated int bar = 1;
  }
  Bars bars = 1;
}
  

И затем проверьте

 foo.bars.SetInParent()
assert foo.HasField("bars")
  

Таким образом, вы можете определить, не было ли задано повторяющееся поле, потому что не было бы причин добавлять сообщение bars в foo, если не было намерения добавить bar .

Ответ №3:

Учитывая msg переменную с сообщением, вы можете печатать только повторяющиеся поля, подобные этому. из C # docs

 for descr in msg.DESCRIPTOR.fields:
    if descr.label == descr.LABEL_REPEATED:
        print(f'{descr.name} is repeated')
        for i, v_i in enumerate(getattr(msg, descr.name)):
            print(f'{i}:{v_i}')
  

Комментарии:

1. Я точно искал, как проверить, есть ли поле repeated . Спасибо!

Ответ №4:

Повторяющиеся поля в файле .proto не поддерживают проверку его существования через has_field_name() .
Следовательно, вы можете проверить размер списка (поскольку повторяющееся поле является списком) и соответствующим образом настроить свою бизнес-логику.

Пример:
рассмотрим ниже файл .proto;

 message XYZ {
  optional int64 raw_size = 1;

  // Repeated messages list
  message Abc {
    // The line.
    optional string line = 2;
  }

  // List of lines
  repeated Abc abc_list = 3;
}
  

Случай 1:
Проверьте, существует ли ‘raw_size’ в файле .proto.

Решение: XYZ.has_raw_size()

Случай 2: проверьте, существует ли ‘abc_list’ в файле .proto.
Решение: XYZ.abc_list_size()> 0

Ответ №5:

Как уже говорилось в других ответах, это сработает:

 assert len(foo.bar) == 0
  

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

 assert len(getattr(msg, field_name))
  

где в вашем случае msg это «foo» и field_name «bar».