edtlib: binding: Add a title keyword
Add a 'title' keyword to the binding to provide a short description of the binding, while 'description' serves as the long description. Signed-off-by: James Roy <rruuaanng@outlook.com>
This commit is contained in:
parent
b1775914d6
commit
ee17657ad3
@ -580,7 +580,14 @@ def print_binding_page(binding, base_names, vnd_lookup, driver_sources,dup_compa
|
||||
|
||||
{bus_help}
|
||||
''', string_io)
|
||||
print(to_code_block(binding.description.strip()), file=string_io)
|
||||
|
||||
if binding.title:
|
||||
description = ("\n\n"
|
||||
.join([binding.title, binding.description])
|
||||
.strip())
|
||||
else:
|
||||
description = binding.description.strip()
|
||||
print(to_code_block(description), file=string_io)
|
||||
|
||||
# Properties.
|
||||
print_block('''\
|
||||
|
||||
18
doc/build/dts/bindings-syntax.rst
vendored
18
doc/build/dts/bindings-syntax.rst
vendored
@ -19,6 +19,16 @@ like this:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
# When the description text is too long, this field can
|
||||
# be used to improve readability, e.g.:
|
||||
#
|
||||
# title: Binding the device's hardware model.
|
||||
#
|
||||
# description |
|
||||
# A piece of content with 20 lines.
|
||||
# ...
|
||||
title: Concise title for the long description [optional]
|
||||
|
||||
# A high level description of the device the binding applies to:
|
||||
description: |
|
||||
This is the Vendomatic company's foo-device.
|
||||
@ -58,6 +68,14 @@ like this:
|
||||
|
||||
These keys are explained in the following sections.
|
||||
|
||||
.. _dt-bindings-title:
|
||||
|
||||
Title
|
||||
*****
|
||||
|
||||
Short description of the bound device, typically the hardware model.
|
||||
(It's optional.)
|
||||
|
||||
.. _dt-bindings-description:
|
||||
|
||||
Description
|
||||
|
||||
2
doc/build/dts/bindings-upstream.rst
vendored
2
doc/build/dts/bindings-upstream.rst
vendored
@ -83,6 +83,8 @@ style:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
title: I'm sure you need a short title.
|
||||
|
||||
description: |
|
||||
My very long string
|
||||
goes here.
|
||||
|
||||
@ -114,8 +114,21 @@ class Binding:
|
||||
path:
|
||||
The absolute path to the file defining the binding.
|
||||
|
||||
title:
|
||||
The free-form title of the binding (optional).
|
||||
|
||||
When the content in the 'description:' is too long, the 'title:' can
|
||||
be used as a heading for the extended description. Typically, it serves
|
||||
as a description of the hardware model. For example:
|
||||
|
||||
title: Nordic GPIO
|
||||
|
||||
description: |
|
||||
Descriptions and example nodes related to GPIO.
|
||||
...
|
||||
|
||||
description:
|
||||
The free-form description of the binding, or None.
|
||||
The free-form description of the binding.
|
||||
|
||||
compatible:
|
||||
The compatible string the binding matches.
|
||||
@ -173,7 +186,7 @@ class Binding:
|
||||
|
||||
def __init__(self, path: Optional[str], fname2path: dict[str, str],
|
||||
raw: Any = None, require_compatible: bool = True,
|
||||
require_description: bool = True):
|
||||
require_description: bool = True, require_title: bool = False):
|
||||
"""
|
||||
Binding constructor.
|
||||
|
||||
@ -201,6 +214,12 @@ class Binding:
|
||||
"description:" line. If False, a missing "description:" is
|
||||
not an error. Either way, "description:" must be a string
|
||||
if it is present in the binding.
|
||||
|
||||
require_title:
|
||||
If True, it is an error if the binding does not contain a
|
||||
"title:" line. If False, a missing "title:" is not an error.
|
||||
Either way, "title:" must be a string if it is present in
|
||||
the binding.
|
||||
"""
|
||||
self.path: Optional[str] = path
|
||||
self._fname2path: dict[str, str] = fname2path
|
||||
@ -217,8 +236,8 @@ class Binding:
|
||||
self.raw: dict = self._merge_includes(raw, self.path)
|
||||
|
||||
# Recursively initialize any child bindings. These don't
|
||||
# require a 'compatible' or 'description' to be well defined,
|
||||
# but they must be dicts.
|
||||
# require a 'compatible', 'description' or 'title' to be well
|
||||
# defined, but they must be dicts.
|
||||
if "child-binding" in raw:
|
||||
if not isinstance(raw["child-binding"], dict):
|
||||
_err(f"malformed 'child-binding:' in {self.path}, "
|
||||
@ -232,7 +251,7 @@ class Binding:
|
||||
self.child_binding = None
|
||||
|
||||
# Make sure this is a well defined object.
|
||||
self._check(require_compatible, require_description)
|
||||
self._check(require_compatible, require_description, require_title)
|
||||
|
||||
# Initialize look up tables.
|
||||
self.prop2specs: dict[str, PropertySpec] = {}
|
||||
@ -251,6 +270,11 @@ class Binding:
|
||||
basename = os.path.basename(self.path or "")
|
||||
return f"<Binding {basename}" + compat + ">"
|
||||
|
||||
@property
|
||||
def title(self) -> Optional[str]:
|
||||
"See the class docstring"
|
||||
return self.raw.get('title')
|
||||
|
||||
@property
|
||||
def description(self) -> Optional[str]:
|
||||
"See the class docstring"
|
||||
@ -364,7 +388,8 @@ class Binding:
|
||||
|
||||
return self._merge_includes(contents, path)
|
||||
|
||||
def _check(self, require_compatible: bool, require_description: bool):
|
||||
def _check(self, require_compatible: bool, require_description: bool,
|
||||
require_title: bool):
|
||||
# Does sanity checking on the binding.
|
||||
|
||||
raw = self.raw
|
||||
@ -378,6 +403,13 @@ class Binding:
|
||||
elif require_compatible:
|
||||
_err(f"missing 'compatible' in {self.path}")
|
||||
|
||||
if "title" in raw:
|
||||
title = raw["title"]
|
||||
if not isinstance(title, str) or not title:
|
||||
_err(f"malformed or empty 'title' in {self.path}")
|
||||
elif require_title:
|
||||
_err(f"missing 'title' in {self.path}")
|
||||
|
||||
if "description" in raw:
|
||||
description = raw["description"]
|
||||
if not isinstance(description, str) or not description:
|
||||
@ -387,8 +419,8 @@ class Binding:
|
||||
|
||||
# Allowed top-level keys. The 'include' key should have been
|
||||
# removed by _load_raw() already.
|
||||
ok_top = {"description", "compatible", "bus", "on-bus",
|
||||
"properties", "child-binding"}
|
||||
ok_top = {"title", "description", "compatible", "bus",
|
||||
"on-bus", "properties", "child-binding"}
|
||||
|
||||
# Descriptive errors for legacy bindings.
|
||||
legacy_errors = {
|
||||
@ -398,7 +430,6 @@ class Binding:
|
||||
"parent": "use 'on-bus: <bus>' instead",
|
||||
"parent-bus": "use 'on-bus: <bus>' instead",
|
||||
"sub-node": "use 'child-binding' instead",
|
||||
"title": "use 'description' instead",
|
||||
}
|
||||
|
||||
for key in raw:
|
||||
@ -3328,7 +3359,8 @@ _DEFAULT_PROP_BINDING: Binding = Binding(
|
||||
for name in _DEFAULT_PROP_TYPES
|
||||
},
|
||||
},
|
||||
require_compatible=False, require_description=False,
|
||||
require_compatible=False,
|
||||
require_description=False,
|
||||
)
|
||||
|
||||
_DEFAULT_PROP_SPECS: dict[str, PropertySpec] = {
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
title: Test binding
|
||||
|
||||
description: Property default value test
|
||||
|
||||
compatible: "defaults"
|
||||
|
||||
@ -531,6 +531,20 @@ def test_bus():
|
||||
assert str(edt.get_node("/buses/foo-bus/node1/nested").binding_path) == \
|
||||
hpath("test-bindings/device-on-foo-bus.yaml")
|
||||
|
||||
def test_binding_top_key():
|
||||
fname2path = {'include.yaml': 'test-bindings-include/include.yaml',
|
||||
'include-2.yaml': 'test-bindings-include/include-2.yaml'}
|
||||
|
||||
with from_here():
|
||||
binding = edtlib.Binding("test-bindings/defaults.yaml", fname2path)
|
||||
title = binding.title
|
||||
description = binding.description
|
||||
compatible = binding.compatible
|
||||
|
||||
assert title == "Test binding"
|
||||
assert description == "Property default value test"
|
||||
assert compatible == "defaults"
|
||||
|
||||
def test_child_binding():
|
||||
'''Test 'child-binding:' in bindings'''
|
||||
with from_here():
|
||||
|
||||
Loading…
Reference in New Issue
Block a user