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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.