Package: bbfreport
Broadband Forum (BBF) Data Model Report ToolNote: The v2+ version might suggest that the tool is mature, but the
v2 label is just to distinguish it from the earlierreport.pltool. APIs
are still liable to minor change, and will probably continue to do so
until v3.TheBBFReport Tool processes one or moreData Model (DM) XML files.
Having read the files, it always performs various "lint" checks, and then it
optionally generates an output format, e.g., "full" XML (a single file in
which all imports have been resolved) or markdown (which can be converted to
HTML bypandoc).The tool requires at leastpython3.9, and can be installed fromPyPI.
It replaces an earlierreport.pltool.Quick startEnsure you have at least python 3.9, and install the tool from PyPI.% python -m pip install bbfreportThereport.pycommand should now work.% report.py -v
Broadband Forum bbfreport v2.0.1 (2023-06-27 version)You'll probably want to download some data models.% git clone https://github.com/BroadbandForum/usp-data-models.git(These are theUSPdata models. TheCWMPdata models are in thecwmp-data-modelsrepository.)Now you can run the tool, e.g., here we're running it on the USP version of
the latestTR-181 (Device:2)model.-I(--include) indicates where to look for DM XML files-l(--loglevel) is here used to suppress warnings (there are some
warnings, because the tool has improved since the data model was published)% report.py -I usp-data-models -l error tr-181-2-usp.xmlTo generate output, give an output format.-f(--format) indicates the output format-o(--output) specifies the output file% report.py -I usp-data-models -l error tr-181-2-usp.xml -f xml -o tr-181-2-usp-full.xmlNote: Direct HTML generation isn't yet supported. It's currently
necessary to generate markdown and then run it throughpandocto
generate the HTML.Unfortunately,report.py -h(--help) doesn't yet list all the available
formats (new-style formats aren't listed), e.g., it doesn't list themarkdownformat.How it worksHere's an outline of what the tool does.Process the command line arguments.
Create an empty node tree.

For each DM file specified on the command line:
    Parse the file using the specified parser (default: expat).
        (this updates the node tree)

For each specified transform (default: [used, lint]):
    Transform the node tree.

Output the specified format (default: null).The node tree (deliberately) has the same structure as the DM XML files,
e.g.,Xml_filenodes haveDm_documentchildren, which haveDescription,DataType,ComponentandModelchildren; andModelnodes haveObject,Parameter,Command,EventandProfilechildren; and so on.Theusedtransform traverses the node tree and determines which data
types, bibliographic references etc. are actually used. If they're not
used then, unless overridden by-A(--all), they're excluded from the
output.Thelinttransform traverses the node tree and performs a large number of
"lint" checks that (as far as possible) check that theTR-106rules and
best practices are being followed.Any transforms specified on the command-line via-t(--transform) are
run before theusedandlinttransforms.Searching for DM XML filesDM XML files (if they don't specify the directory) are always searched for
in the current directory (unless suppressed by-C/--nocurdir) and
(recursively) in the  directories listed via the-I(--include) option.File names of the (conventional) formtr-nnn-i-a-c-label.xmlcan omit-c,-a-cor-i-a-c, in which case the latest matching version will
be used.Note:i,aandcstand forIssue,AmendmentandCorrigendumrespectively. You can think of them as major, minor and
patch versions.Most files (all except for the files specified on the command-line) are
accessed via animportstatement such as this one:<import file="tr-181-2-softwaremodules.xml"
        spec="urn:broadband-forum-org:tr-181-2-17-softwaremodules">
    <component name="SMDUNetworkConfig"/>
</import>If theimportstatement has aspecattribute then a file with a
matchingspecwill be searched for. Here the spec specifiesianda,
so they must match exactly, but it omitsc, so the latestcwill be
returned.Transforms and FormatsTransforms and formats are written in similar ways, but (as already
explained) they have different purposes.There are two ways to write transforms and formats. The old way is to
write a class that derives fromTransformorFormat, and the new (much
easier) way is to write various "magic" functions whose names indicate the
type of node for which they are to be called.Suppose you want to write a transform that checks whether any object,
parameter etc. names start with lower-case letters. You can create thislower.pyfile.def visit__model_item(node, logger):
  if node.name[0].islower():
      logger.info('%s %s' % (node.version_inherited, node.nicepath))There are several things to note here:You have to know something about the node class hierarchy, which is
defined innode.py, and how the class names map
tovisit_xxx()function namesIn this case,_ModelItemis a base class forModel,Object,Parameter,Command,EventandProfileTo generate the function name, the_ModelItemclass name has
underscores inserted between lower/upper transitions, is converted to
lowercase, and is prefixed withvisit_to givevisit__model_item(two underscores, because the class name starts with an underscore)The function's first argument is always the node, and other arguments are
optional (but selected from a predefined set). Here, theloggerargument is a ready-to-useloggerinstance. You could also (for
example) have provided anargsargument if you needed to access the
command-line argumentsYou also have to know something about the node attributes. As already
mentioned, they are very similar to the XML, so for examplenode.nameis the name, andnode.versionis the version... but it's theactualversionattribute, which might need to be inherited from the node's
parent, so that's why we usenode.version_inherited. We also usenode.nicepath, and you couldn't have guessed thisFor more information you'll have to refer to the code or to the code
documentation (once it's available)You can then run the tool like this:% report.py -I usp-data-models tr-181-2-usp.xml -P . -t lower -l 1 -L lowerThe options (some of which are new) are as follows:-I(--include) indicates where to look for DM XML files-P(--plugindir) indicates where to search for transforms and formats-t(--transform) says which transform to run (there could be several)-l(--loglevel) is the log level;1is the same asinfo-L(--loggername) is the logger name; only the top-levelreportlogger is initially enabledHere's the output:INFO:report:processing 'tr-181-2-usp.xml'
INFO:report:processed  'tr-181-2-usp.xml' in 5286 ms
INFO:report:performing 'lower' transform
INFO:lower:2.15 Device.WiFi.<omitted>.bSTAMACAddress
INFO:lower:2.17 Device.WiFi.<omitted>.bSTAMLDMaxLinks
INFO:lower:2.17 Device.WiFi.<omitted>.bSTAMACAddress
INFO:report:performed  'lower' transform in 366 ms
INFO:report:performing 'used' transform
INFO:report:performed  'used' transform in 1327 ms
INFO:report:performing 'lint' transform
INFO:report:performed  'lint' transform in 3944 ms
INFO:report:generating 'null' format
INFO:report:generated  'null' format in 0 msLog levels and loggersThe-l(--loglevel) option sets the log level to one of the
following.ValueDescriptionnoneNo log messages are outputfatalOnly fatal errors are outputerrorOnly fatal and ordinary errors are outputwarningor0All errors and warnings are output (default)infoor1Errors and warnings and info messages are outputdebugor2As above plus debug messagesAs a rule of thumb, info messages should be of interest to all users of
the tool, but debug messages are likely to be only of interest to people
trying to work out what's gone wrong.For info and debug messages, just setting the log level isn't enough. You
have to use the-L(--loggername) option to enable the loggers of
interest. Only the top-levelreportlogger is always enabled.The logger name is the python module name, e.g., the lint transform's
logger name is `lint. Here's an example.% report.py -I usp-data-models tr-140-1-usp.xml -l 1 -L lint -L used
INFO:report:processing 'tr-140-1-usp.xml'
INFO:report:processed  'tr-140-1-usp.xml' in 195 ms
INFO:report:performing 'used' transform
INFO:report:performed  'used' transform in 100 ms
INFO:report:performing 'lint' transform
INFO:lint:StorageService.{i}.StorageArray.{i}.:
     list-valued unique key parameter PhysicalMediumReference
INFO:lint:StorageService.{i}.StorageArray.{i}.Alias:
     list-valued unique key parameter PhysicalMediumReference
INFO:report:performed  'lint' transform in 115 ms
INFO:report:generating 'null' format
INFO:report:generated  'null' format in 0 msNotesThe distribution doesn't contain any sample DM instances, so you have to
download some data models before you can usefully use the tool