From: Dietmar Maurer <dietmar@proxmox.com>
To: pve-devel@lists.proxmox.com, w.bumiller@proxmox.com
Subject: [RFC proxmox] schema: extend SchemaPropertyEntry to include property description
Date: Thu, 29 Jan 2026 17:50:23 +0100 [thread overview]
Message-ID: <20260129165023.4170492-1-dietmar@proxmox.com> (raw)
Enable correct documentation of object properties by extending
SchemaPropertyEntry from a 3-tuple (name, optional, schema) to a
4-tuple (name, optional, schema, description).
Each object property can now have:
- A description for the property itself
- A type with its own separate description
This separation is essential for generating accurate API documentation,
where property descriptions explain the purpose or usage of a property,
while type descriptions explain the data format or constraints.
Update all related code including:
- ObjectSchemaType trait: lookup() now returns (bool, &Schema, &'static str)
- ObjectPropertyIterator: now yields 4-tuples
- Deserialization (extract, verify modules)
- Serialization module
- Format utilities
- All tests and documentation examples
Note: Other crates using proxmox-schema (e.g., proxmox-api-macro,
pve-api-types, pbs-api-types) will need to be updated to properly
utilize property-level descriptions.
Signed-off-by: Dietmar Maurer <dietmar@proxmox.com>
---
| 20 ++---
proxmox-schema/src/de/mod.rs | 2 +-
proxmox-schema/src/de/verify.rs | 4 +-
proxmox-schema/src/format.rs | 8 +-
proxmox-schema/src/property_string.rs | 41 +++++++---
proxmox-schema/src/schema.rs | 83 +++++++++++----------
proxmox-schema/src/ser/mod.rs | 4 +-
proxmox-schema/tests/schema.rs | 36 +++++++--
proxmox-schema/tests/schema_verification.rs | 27 ++++---
9 files changed, 142 insertions(+), 83 deletions(-)
--git a/proxmox-schema/src/de/extract.rs b/proxmox-schema/src/de/extract.rs
index 6166c7b2..8abb2738 100644
--- a/proxmox-schema/src/de/extract.rs
+++ b/proxmox-schema/src/de/extract.rs
@@ -102,15 +102,15 @@ impl<'de> de::Deserializer<'de> for ExtractValueDeserializer<'de> {
match self.schema {
Schema::Object(schema) => visitor.visit_map(MapAccess::<'de>::new(
self.object,
- schema.properties().map(|(name, _, _)| *name),
+ schema.properties().map(|(name, _, _, _)| *name),
)),
Schema::AllOf(schema) => visitor.visit_map(MapAccess::<'de>::new(
self.object,
- schema.properties().map(|(name, _, _)| *name),
+ schema.properties().map(|(name, _, _, _)| *name),
)),
Schema::OneOf(schema) => visitor.visit_map(MapAccess::<'de>::new(
self.object,
- schema.properties().map(|(name, _, _)| *name),
+ schema.properties().map(|(name, _, _, _)| *name),
)),
// The following should be caught by ExtractValueDeserializer::new()!
@@ -134,15 +134,15 @@ impl<'de> de::Deserializer<'de> for ExtractValueDeserializer<'de> {
match self.schema {
Schema::Object(schema) => visitor.visit_map(MapAccess::<'de>::new(
self.object,
- schema.properties().map(|(name, _, _)| *name),
+ schema.properties().map(|(name, _, _, _)| *name),
)),
Schema::AllOf(schema) => visitor.visit_map(MapAccess::<'de>::new(
self.object,
- schema.properties().map(|(name, _, _)| *name),
+ schema.properties().map(|(name, _, _, _)| *name),
)),
Schema::OneOf(schema) => visitor.visit_map(MapAccess::<'de>::new(
self.object,
- schema.properties().map(|(name, _, _)| *name),
+ schema.properties().map(|(name, _, _, _)| *name),
)),
// The following should be caught by ExtractValueDeserializer::new()!
@@ -260,8 +260,8 @@ fn test_extraction() {
const FOO_SCHEMA: Schema = ObjectSchema::new(
"A Foo",
&[
- ("foo1", false, &SIMPLE_STRING),
- ("foo2", false, &SIMPLE_STRING),
+ ("foo1", false, &SIMPLE_STRING, "foo1"),
+ ("foo2", false, &SIMPLE_STRING, "foo2"),
],
)
.schema();
@@ -275,8 +275,8 @@ fn test_extraction() {
const BAR_SCHEMA: Schema = ObjectSchema::new(
"A Bar",
&[
- ("bar1", false, &SIMPLE_STRING),
- ("bar2", false, &SIMPLE_STRING),
+ ("bar1", false, &SIMPLE_STRING, "bar1"),
+ ("bar2", false, &SIMPLE_STRING, "bar2"),
],
)
.schema();
diff --git a/proxmox-schema/src/de/mod.rs b/proxmox-schema/src/de/mod.rs
index ca6b4981..9ebd0240 100644
--- a/proxmox-schema/src/de/mod.rs
+++ b/proxmox-schema/src/de/mod.rs
@@ -642,7 +642,7 @@ impl<'de> de::MapAccess<'de> for MapAccess<'de, '_> {
}
},
};
- let schema = schema.map(|(_optional, schema)| schema);
+ let schema = schema.map(|(_optional, schema, _description)| schema);
let out = match &key {
Cow::Borrowed(key) => {
diff --git a/proxmox-schema/src/de/verify.rs b/proxmox-schema/src/de/verify.rs
index 0b2834ff..09c5d0b5 100644
--- a/proxmox-schema/src/de/verify.rs
+++ b/proxmox-schema/src/de/verify.rs
@@ -238,7 +238,7 @@ impl<'de> de::Visitor<'de> for Visitor {
// The tests need this to be in a predictable order, so HashSet won't work as it uses a
// randomized default state.
let mut required_keys = BTreeSet::<&'static str>::new();
- for (key, optional, _schema) in schema.properties() {
+ for (key, optional, _schema, _description) in schema.properties() {
if !optional {
required_keys.insert(key);
}
@@ -252,7 +252,7 @@ impl<'de> de::Visitor<'de> for Visitor {
};
let _guard = match schema.lookup(&key) {
- Some((optional, schema)) => {
+ Some((optional, schema, _description)) => {
if !optional {
// required keys are only tracked in the required_keys hashset
if !required_keys.remove(key.as_ref()) {
diff --git a/proxmox-schema/src/format.rs b/proxmox-schema/src/format.rs
index 080b0268..36db5648 100644
--- a/proxmox-schema/src/format.rs
+++ b/proxmox-schema/src/format.rs
@@ -147,7 +147,7 @@ pub fn dump_properties(
let mut required_list: Vec<String> = Vec::new();
let mut optional_list: Vec<String> = Vec::new();
- for (prop, optional, schema) in param.properties() {
+ for (prop, optional, schema, _description) in param.properties() {
if skip.iter().any(|n| n == prop) {
continue;
}
@@ -390,12 +390,12 @@ fn get_object_type_text(object_schema: &ObjectSchema) -> String {
// add default key first
if let Some(ref default_key) = object_schema.default_key {
- let (optional, schema) = object_schema.lookup(default_key).unwrap();
+ let (optional, schema, _description) = object_schema.lookup(default_key).unwrap();
add_part(default_key, optional, schema);
}
// add required keys
- for (name, optional, schema) in object_schema.properties {
+ for (name, optional, schema, _description) in object_schema.properties {
if *optional {
continue;
}
@@ -408,7 +408,7 @@ fn get_object_type_text(object_schema: &ObjectSchema) -> String {
}
// add options keys
- for (name, optional, schema) in object_schema.properties {
+ for (name, optional, schema, _description) in object_schema.properties {
if !*optional {
continue;
}
diff --git a/proxmox-schema/src/property_string.rs b/proxmox-schema/src/property_string.rs
index b9351a6b..e8e589e7 100644
--- a/proxmox-schema/src/property_string.rs
+++ b/proxmox-schema/src/property_string.rs
@@ -375,13 +375,19 @@ mod test {
"An object",
&[
// MUST BE SORTED
- ("count", false, &IntegerSchema::new("name").schema()),
- ("name", false, &StringSchema::new("name").schema()),
- ("nested", true, &Nested::API_SCHEMA),
+ (
+ "count",
+ false,
+ &IntegerSchema::new("name").schema(),
+ "count",
+ ),
+ ("name", false, &StringSchema::new("name").schema(), "name"),
+ ("nested", true, &Nested::API_SCHEMA, "nested"),
(
"optional",
true,
&BooleanSchema::new("an optional boolean").schema(),
+ "optional",
),
],
)
@@ -407,9 +413,10 @@ mod test {
"count",
true,
&ArraySchema::new("count", &IntegerSchema::new("a value").schema()).schema(),
+ "count",
),
- ("name", false, &StringSchema::new("name").schema()),
- ("third", true, &Third::API_SCHEMA),
+ ("name", false, &StringSchema::new("name").schema(), "name"),
+ ("third", true, &Third::API_SCHEMA, "third"),
],
)
.schema();
@@ -431,8 +438,13 @@ mod test {
"An object",
&[
// MUST BE SORTED
- ("count", false, &IntegerSchema::new("name").schema()),
- ("name", false, &StringSchema::new("name").schema()),
+ (
+ "count",
+ false,
+ &IntegerSchema::new("name").schema(),
+ "count",
+ ),
+ ("name", false, &StringSchema::new("name").schema(), "name"),
],
)
.schema();
@@ -485,9 +497,20 @@ mod test {
"disconnected",
true,
&BooleanSchema::new("disconnected").schema(),
+ "disconnected",
+ ),
+ (
+ "macaddr",
+ false,
+ &StringSchema::new("macaddr").schema(),
+ "macaddr",
+ ),
+ (
+ "model",
+ false,
+ &StringSchema::new("model").schema(),
+ "model",
),
- ("macaddr", false, &StringSchema::new("macaddr").schema()),
- ("model", false, &StringSchema::new("model").schema()),
],
)
.key_alias_info(crate::schema::KeyAliasInfo::new(
diff --git a/proxmox-schema/src/schema.rs b/proxmox-schema/src/schema.rs
index 40ede2f1..e1356f05 100644
--- a/proxmox-schema/src/schema.rs
+++ b/proxmox-schema/src/schema.rs
@@ -631,7 +631,8 @@ impl ArraySchema {
/// - `name`: The name of the property
/// - `optional`: Set when the property is optional
/// - `schema`: Property type schema
-pub type SchemaPropertyEntry = (&'static str, bool, &'static Schema);
+/// - `description`: Property description
+pub type SchemaPropertyEntry = (&'static str, bool, &'static Schema, &'static str);
/// Lookup table to Schema properties
///
@@ -727,8 +728,8 @@ impl ObjectSchema {
/// const SCHEMA: Schema = ObjectSchema::new(
/// "Some Object",
/// &[
- /// ("key1", false, &StringSchema::new("A String").schema()),
- /// ("key2", false, &StringSchema::new("Another String").schema()),
+ /// ("key1", false, &StringSchema::new("A String").schema(), "A String"),
+ /// ("key2", false, &StringSchema::new("Another String").schema(), "Another String"),
/// ],
/// ).schema();
/// ```
@@ -740,8 +741,8 @@ impl ObjectSchema {
/// const SCHEMA: Schema = ObjectSchema::new(
/// "Some Object",
/// &[
- /// ("wrong", false, &StringSchema::new("A String").schema()),
- /// ("order", false, &StringSchema::new("Another String").schema()),
+ /// ("wrong", false, &StringSchema::new("A String").schema(), "A String"),
+ /// ("order", false, &StringSchema::new("Another String").schema(), "Another String"),
/// ],
/// ).schema();
/// ```
@@ -751,9 +752,9 @@ impl ObjectSchema {
/// const SCHEMA: Schema = ObjectSchema::new(
/// "Some Object",
/// &[
- /// ("same", false, &StringSchema::new("A String").schema()),
+ /// ("same", false, &StringSchema::new("A String").schema(), "A String"),
/// // duplicate field name:
- /// ("same", false, &StringSchema::new("Another String").schema()),
+ /// ("same", false, &StringSchema::new("Another String").schema(), "Another String"),
/// ],
/// ).schema();
/// ```
@@ -782,13 +783,13 @@ impl ObjectSchema {
Schema::Object(self)
}
- pub fn lookup(&self, key: &str) -> Option<(bool, &Schema)> {
+ pub fn lookup(&self, key: &str) -> Option<(bool, &Schema, &'static str)> {
if let Ok(ind) = self
.properties
- .binary_search_by_key(&key, |(name, _, _)| name)
+ .binary_search_by_key(&key, |(name, _, _, _)| name)
{
- let (_name, optional, prop_schema) = self.properties[ind];
- Some((optional, prop_schema))
+ let (_name, optional, prop_schema, prop_description) = self.properties[ind];
+ Some((optional, prop_schema, prop_description))
} else {
None
}
@@ -844,7 +845,7 @@ impl AllOfSchema {
Schema::AllOf(self)
}
- pub fn lookup(&self, key: &str) -> Option<(bool, &Schema)> {
+ pub fn lookup(&self, key: &str) -> Option<(bool, &Schema, &'static str)> {
for entry in self.list {
if let Some(v) = entry
.any_object()
@@ -926,20 +927,20 @@ impl OneOfSchema {
/// # const SCHEMA_V1: Schema = ObjectSchema::new(
/// # "Some Object",
/// # &[
- /// # ("key1", false, &StringSchema::new("A String").schema()),
- /// # ("key2", false, &StringSchema::new("Another String").schema()),
+ /// # ("key1", false, &StringSchema::new("A String").schema(), "A String"),
+ /// # ("key2", false, &StringSchema::new("Another String").schema(), "Another String"),
/// # ],
/// # ).schema();
/// # const SCHEMA_V2: Schema = ObjectSchema::new(
/// # "Another Object",
/// # &[
- /// # ("key3", false, &StringSchema::new("A String").schema()),
- /// # ("key4", false, &StringSchema::new("Another String").schema()),
+ /// # ("key3", false, &StringSchema::new("A String").schema(), "A String"),
+ /// # ("key4", false, &StringSchema::new("Another String").schema(), "Another String"),
/// # ],
/// # ).schema();
/// const SCHEMA: Schema = OneOfSchema::new(
/// "Some enum",
- /// &("type", false, &StringSchema::new("v1 or v2").schema()),
+ /// &("type", false, &StringSchema::new("v1 or v2").schema(), "v1 or v2"),
/// &[
/// ("v1", &SCHEMA_V1),
/// ("v2", &SCHEMA_V2),
@@ -954,20 +955,20 @@ impl OneOfSchema {
/// # const SCHEMA_V1: Schema = ObjectSchema::new(
/// # "Some Object",
/// # &[
- /// # ("key1", false, &StringSchema::new("A String").schema()),
- /// # ("key2", false, &StringSchema::new("Another String").schema()),
+ /// # ("key1", false, &StringSchema::new("A String").schema(), "A String"),
+ /// # ("key2", false, &StringSchema::new("Another String").schema(), "Another String"),
/// # ],
/// # ).schema();
/// # const SCHEMA_V2: Schema = ObjectSchema::new(
/// # "Another Object",
/// # &[
- /// # ("key3", false, &StringSchema::new("A String").schema()),
- /// # ("key4", false, &StringSchema::new("Another String").schema()),
+ /// # ("key3", false, &StringSchema::new("A String").schema(), "A String"),
+ /// # ("key4", false, &StringSchema::new("Another String").schema(), "Another String"),
/// # ],
/// # ).schema();
/// const SCHEMA: Schema = OneOfSchema::new(
/// "Some enum",
- /// &("type", false, &StringSchema::new("v1 or v2").schema()),
+ /// &("type", false, &StringSchema::new("v1 or v2").schema(), "v1 or v2"),
/// &[
/// ("v2", &SCHEMA_V1),
/// ("v1", &SCHEMA_V2),
@@ -980,20 +981,20 @@ impl OneOfSchema {
/// # const SCHEMA_V1: Schema = ObjectSchema::new(
/// # "Some Object",
/// # &[
- /// # ("key1", false, &StringSchema::new("A String").schema()),
- /// # ("key2", false, &StringSchema::new("Another String").schema()),
+ /// # ("key1", false, &StringSchema::new("A String").schema(), "A String"),
+ /// # ("key2", false, &StringSchema::new("Another String").schema(), "Another String"),
/// # ],
/// # ).schema();
/// # const SCHEMA_V2: Schema = ObjectSchema::new(
/// # "Another Object",
/// # &[
- /// # ("key3", false, &StringSchema::new("A String").schema()),
- /// # ("key4", false, &StringSchema::new("Another String").schema()),
+ /// # ("key3", false, &StringSchema::new("A String").schema(), "A String"),
+ /// # ("key4", false, &StringSchema::new("Another String").schema(), "Another String"),
/// # ],
/// # ).schema();
/// const SCHEMA: Schema = OneOfSchema::new(
/// "Some enum",
- /// &("type", false, &StringSchema::new("v1 or v2").schema()),
+ /// &("type", false, &StringSchema::new("v1 or v2").schema(), "v1 or v2"),
/// &[
/// ("v1", &SCHEMA_V1),
/// // duplicate type key:
@@ -1026,9 +1027,9 @@ impl OneOfSchema {
self.type_property_entry.2
}
- pub fn lookup(&self, key: &str) -> Option<(bool, &Schema)> {
+ pub fn lookup(&self, key: &str) -> Option<(bool, &Schema, &'static str)> {
if key == self.type_property() {
- return Some((false, self.type_schema()));
+ return Some((false, self.type_schema(), self.type_property_entry.3));
}
for (_variant, entry) in self.list {
@@ -1078,7 +1079,7 @@ mod private {
/// Beside [`ObjectSchema`] we also have an [`AllOfSchema`] which also represents objects.
pub trait ObjectSchemaType: private::Sealed + Send + Sync {
fn description(&self) -> &'static str;
- fn lookup(&self, key: &str) -> Option<(bool, &Schema)>;
+ fn lookup(&self, key: &str) -> Option<(bool, &Schema, &'static str)>;
fn properties(&self) -> ObjectPropertyIterator;
fn additional_properties(&self) -> bool;
fn default_key(&self) -> Option<&'static str>;
@@ -1101,7 +1102,7 @@ pub trait ObjectSchemaType: private::Sealed + Send + Sync {
let additional_properties = self.additional_properties();
for (key, value) in map {
- if let Some((_optional, prop_schema)) = self.lookup(key) {
+ if let Some((_optional, prop_schema, _prop_description)) = self.lookup(key) {
if let Err(err) = prop_schema.verify_json(value) {
errors.add_errors(key, err);
};
@@ -1113,7 +1114,7 @@ pub trait ObjectSchemaType: private::Sealed + Send + Sync {
}
}
- for (name, optional, _prop_schema) in self.properties() {
+ for (name, optional, _prop_schema, _prop_description) in self.properties() {
if !(*optional) && data[name] == Value::Null {
errors.push(
name.to_string(),
@@ -1152,7 +1153,7 @@ impl ObjectSchemaType for ObjectSchema {
self.description
}
- fn lookup(&self, key: &str) -> Option<(bool, &Schema)> {
+ fn lookup(&self, key: &str) -> Option<(bool, &Schema, &'static str)> {
ObjectSchema::lookup(self, key)
}
@@ -1182,7 +1183,7 @@ impl ObjectSchemaType for AllOfSchema {
self.description
}
- fn lookup(&self, key: &str) -> Option<(bool, &Schema)> {
+ fn lookup(&self, key: &str) -> Option<(bool, &Schema, &'static str)> {
AllOfSchema::lookup(self, key)
}
@@ -1257,7 +1258,7 @@ impl ObjectSchemaType for OneOfSchema {
self.description
}
- fn lookup(&self, key: &str) -> Option<(bool, &Schema)> {
+ fn lookup(&self, key: &str) -> Option<(bool, &Schema, &'static str)> {
OneOfSchema::lookup(self, key)
}
@@ -1361,14 +1362,16 @@ impl Iterator for OneOfPropertyIterator {
/// &IntegerSchema::new("A required integer property.")
/// .minimum(0)
/// .maximum(100)
-/// .schema()
+/// .schema(),
+/// "A required integer property.",
/// ),
/// (
/// "property_two",
/// true /* optional */,
/// &BooleanSchema::new("An optional boolean property.")
/// .default(true)
-/// .schema()
+/// .schema(),
+/// "An optional boolean property.",
/// ),
/// ],
/// ).schema();
@@ -1889,7 +1892,7 @@ impl ObjectSchemaType for ParameterSchema {
}
}
- fn lookup(&self, key: &str) -> Option<(bool, &Schema)> {
+ fn lookup(&self, key: &str) -> Option<(bool, &Schema, &'static str)> {
match self {
ParameterSchema::Object(o) => o.lookup(key),
ParameterSchema::AllOf(o) => o.lookup(key),
@@ -1964,7 +1967,7 @@ fn do_parse_parameter_strings(
let additional_properties = schema.additional_properties();
for (key, value) in data {
- if let Some((_optional, prop_schema)) = schema.lookup(key) {
+ if let Some((_optional, prop_schema, _description)) = schema.lookup(key) {
match prop_schema {
Schema::Array(array_schema) => {
if params[key] == Value::Null {
@@ -2016,7 +2019,7 @@ fn do_parse_parameter_strings(
}
if test_required && errors.is_empty() {
- for (name, optional, _prop_schema) in schema.properties() {
+ for (name, optional, _prop_schema, _description) in schema.properties() {
if !(*optional) && params[name] == Value::Null {
errors.push(
name.to_string(),
diff --git a/proxmox-schema/src/ser/mod.rs b/proxmox-schema/src/ser/mod.rs
index e19209a8..9a4dddba 100644
--- a/proxmox-schema/src/ser/mod.rs
+++ b/proxmox-schema/src/ser/mod.rs
@@ -221,7 +221,9 @@ impl<T: fmt::Write> SerializeStruct<T> {
}
if let Some(schema) = self.schema {
- self.value_schema = schema.lookup(&key).map(|(_optional, schema)| schema);
+ self.value_schema = schema
+ .lookup(&key)
+ .map(|(_optional, schema, _description)| schema);
if self.value_schema.is_none() && !schema.additional_properties() {
return Err(Error::msg(format!(
"key {key:?} is not part of the schema and it does not allow additional properties"
diff --git a/proxmox-schema/tests/schema.rs b/proxmox-schema/tests/schema.rs
index 24c32bef..f81bd2b7 100644
--- a/proxmox-schema/tests/schema.rs
+++ b/proxmox-schema/tests/schema.rs
@@ -30,7 +30,7 @@ fn test_query_string() {
{
const SCHEMA: ObjectSchema = ObjectSchema::new(
"Parameters.",
- &[("name", false, &StringSchema::new("Name.").schema())],
+ &[("name", false, &StringSchema::new("Name.").schema(), "Name.")],
);
let res = parse_query_string("", &SCHEMA, true);
@@ -40,7 +40,7 @@ fn test_query_string() {
{
const SCHEMA: ObjectSchema = ObjectSchema::new(
"Parameters.",
- &[("name", true, &StringSchema::new("Name.").schema())],
+ &[("name", true, &StringSchema::new("Name.").schema(), "Name.")],
);
let res = parse_query_string("", &SCHEMA, true);
@@ -58,6 +58,7 @@ fn test_query_string() {
.min_length(5)
.max_length(10)
.schema(),
+ "Name.",
)],
);
@@ -89,6 +90,7 @@ fn test_query_string() {
&StringSchema::new("Name.")
.format(&ApiStringFormat::Pattern(&TEST_REGEX))
.schema(),
+ "Name.",
)],
);
@@ -108,6 +110,7 @@ fn test_query_string() {
&StringSchema::new("Name.")
.format(&ApiStringFormat::Pattern(&TEST2_REGEX))
.schema(),
+ "Name.",
)],
);
@@ -131,6 +134,7 @@ fn test_query_string() {
EnumEntry::new("ev2", "desc ev2"),
]))
.schema(),
+ "Name.",
)],
);
@@ -153,7 +157,12 @@ fn test_query_integer() {
{
const SCHEMA: ObjectSchema = ObjectSchema::new(
"Parameters.",
- &[("count", false, &IntegerSchema::new("Count.").schema())],
+ &[(
+ "count",
+ false,
+ &IntegerSchema::new("Count.").schema(),
+ "Count.",
+ )],
);
let res = parse_query_string("", &SCHEMA, true);
@@ -170,6 +179,7 @@ fn test_query_integer() {
.minimum(-3)
.maximum(50)
.schema(),
+ "Count.",
)],
);
@@ -204,7 +214,12 @@ fn test_query_boolean() {
{
const SCHEMA: ObjectSchema = ObjectSchema::new(
"Parameters.",
- &[("force", false, &BooleanSchema::new("Force.").schema())],
+ &[(
+ "force",
+ false,
+ &BooleanSchema::new("Force.").schema(),
+ "Force.",
+ )],
);
let res = parse_query_string("", &SCHEMA, true);
@@ -214,7 +229,12 @@ fn test_query_boolean() {
{
const SCHEMA: ObjectSchema = ObjectSchema::new(
"Parameters.",
- &[("force", true, &BooleanSchema::new("Force.").schema())],
+ &[(
+ "force",
+ true,
+ &BooleanSchema::new("Force.").schema(),
+ "Force.",
+ )],
);
let res = parse_query_string("", &SCHEMA, true);
@@ -263,6 +283,7 @@ fn test_verify_function() {
bail!("format error");
}))
.schema(),
+ "P1",
)],
);
@@ -286,6 +307,7 @@ fn test_verify_complex_object() {
"enable",
true,
&BooleanSchema::new("Enable device.").schema(),
+ "Enable device.",
),
(
"model",
@@ -293,6 +315,7 @@ fn test_verify_complex_object() {
&StringSchema::new("Ethernet device Model.")
.format(&NIC_MODELS)
.schema(),
+ "Ethernet device Model.",
),
],
)
@@ -307,6 +330,7 @@ fn test_verify_complex_object() {
&StringSchema::new("First Network device.")
.format(&ApiStringFormat::PropertyString(&PARAM_SCHEMA))
.schema(),
+ "First Network device.",
)],
);
@@ -343,6 +367,7 @@ fn test_verify_complex_array() {
&StringSchema::new("A list on integers, comma separated.")
.format(&ApiStringFormat::PropertyString(&PARAM_SCHEMA))
.schema(),
+ "A list on integers, comma separated.",
)],
);
@@ -377,6 +402,7 @@ fn test_verify_complex_array() {
&StringSchema::new("A list on integers, comma separated.")
.format(&ApiStringFormat::PropertyString(&PARAM_SCHEMA))
.schema(),
+ "A list on integers, comma separated.",
)],
);
diff --git a/proxmox-schema/tests/schema_verification.rs b/proxmox-schema/tests/schema_verification.rs
index c7f43876..c1965f3a 100644
--- a/proxmox-schema/tests/schema_verification.rs
+++ b/proxmox-schema/tests/schema_verification.rs
@@ -8,9 +8,9 @@ static STRING_SCHEMA: Schema = StringSchema::new("A test string").schema();
static SIMPLE_OBJECT_SCHEMA: Schema = ObjectSchema::new(
"simple object schema",
&[
- ("prop1", false, &STRING_SCHEMA),
- ("prop2", true, &STRING_SCHEMA),
- ("prop3", false, &STRING_SCHEMA),
+ ("prop1", false, &STRING_SCHEMA, "A test string"),
+ ("prop2", true, &STRING_SCHEMA, "A test string"),
+ ("prop3", false, &STRING_SCHEMA, "A test string"),
],
)
.schema();
@@ -24,24 +24,29 @@ static SIMPLE_ARRAY_SCHEMA: Schema = ArraySchema::new("String list.", &STRING_SC
static NESTED_OBJECT_SCHEMA: Schema = ObjectSchema::new(
"nested object schema",
&[
- ("arr1", false, &SIMPLE_ARRAY_SCHEMA),
- ("obj1", false, &SIMPLE_OBJECT_SCHEMA),
- ("prop1", false, &STRING_SCHEMA),
+ ("arr1", false, &SIMPLE_ARRAY_SCHEMA, "String list."),
+ ("obj1", false, &SIMPLE_OBJECT_SCHEMA, "Nested object"),
+ ("prop1", false, &STRING_SCHEMA, "A test string"),
],
)
.schema();
static NESTED_PROPERTY_SCHEMA: Schema = ObjectSchema::new(
"object with property strings",
- &[("ps1", false, &SIMPLE_PROPERTY_STRING_SCHEMA)],
+ &[(
+ "ps1",
+ false,
+ &SIMPLE_PROPERTY_STRING_SCHEMA,
+ "simple property string",
+ )],
)
.schema();
static ANOTHER_OBJECT_SCHEMA: Schema = ObjectSchema::new(
"another simple object schema",
&[
- ("another1", false, &STRING_SCHEMA),
- ("another2", true, &STRING_SCHEMA),
+ ("another1", false, &STRING_SCHEMA, "A test string"),
+ ("another2", true, &STRING_SCHEMA, "A test string"),
],
)
.schema();
@@ -49,8 +54,8 @@ static ANOTHER_OBJECT_SCHEMA: Schema = ObjectSchema::new(
static OBJECT_WITH_ADDITIONAL: Schema = ObjectSchema::new(
"object allowing additional properties",
&[
- ("regular1", false, &STRING_SCHEMA),
- ("regular2", true, &STRING_SCHEMA),
+ ("regular1", false, &STRING_SCHEMA, "A test string"),
+ ("regular2", true, &STRING_SCHEMA, "A test string"),
],
)
.additional_properties(true)
--
2.47.3
reply other threads:[~2026-01-29 16:50 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260129165023.4170492-1-dietmar@proxmox.com \
--to=dietmar@proxmox.com \
--cc=pve-devel@lists.proxmox.com \
--cc=w.bumiller@proxmox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox