Skip to content

Commit

Permalink
Various fixes in tools/ to improve code generation (#199)
Browse files Browse the repository at this point in the history
* Fixed excessive newlines

* Fixed unquoted variables; fixed directory issues caused by unzipping into current directory; updated schema version to latest; minor fixes

* Switched to regex based cleanup; added double space cleanup; switched to int-based schema version selection; minor fixes
  • Loading branch information
pallasscat authored Oct 3, 2022
1 parent 243da4e commit 5fb1a98
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 52 deletions.
13 changes: 6 additions & 7 deletions tools/gen_script.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ PYTHON="python3"
#
# Inspect the url for the schema you want - for example, the 2020.1 update
# document is "DSP8010_2020.1.zip" on this page. The base name then is:
schemadoc="DSP8010_2020.4"
schemadoc="DSP8010_2022.2"

# Check if filename provided on the command line
if [[ "$#" -eq 1 ]]; then
Expand All @@ -42,24 +42,23 @@ if [[ ! -d $schemadoc ]]; then
if [[ ! -f "${schemadoc}.zip" ]]; then
# Use curl instead of wget because it is more likely to be present
echo "Fetching schema document $schemadoc"
curl -G -L "https://www.dmtf.org/sites/default/files/standards/documents/${schemadoc}.zip" > ${schemadoc}.zip
curl -G -L "https://www.dmtf.org/sites/default/files/standards/documents/${schemadoc}.zip" > "${schemadoc}.zip"
fi

echo "Extracting schema files..."
unzip "${schemadoc}.zip"
unzip -q "${schemadoc}.zip" -d "${schemadoc}"
fi

# Generate the object list. Not elegant, but it works well enough for now.
#
# SerialInterface and Switch still have some identifier issues to be worked out
# Collection files, Schedule, Protocol are "common" and included differently
# Collection files, Schedule, are "common" and included differently
# redfish-schema, odata and all the versions of each object aren't needed
#
# General process is get a list of the json-schema objects from the zip, drop
# things we don't need/want, and clip the column we want generating a file of
# object names we can use later.
schema_paths=$(find "$schemadoc" -name *.json)
schema_objects=$(find "$schemadoc" -name *json | cut -d '/' -f 3 | cut -d . -f 1 | grep -v Collection | grep -v "redfish-" | grep -v odata | grep -v Protocol | sort | uniq)
schema_objects=$(find "${schemadoc}/json-schema" -name "*.json" | cut -d '/' -f 3 | cut -d '.' -f 1 | grep -Fiv -e 'collection' -e 'redfish-' -e 'odata' -e 'protocol' | sort | uniq )

# Now we're ready to generate the go source based on these files
if [[ ! -d gofiles ]]; then
Expand All @@ -69,7 +68,7 @@ fi
# Loop through each one and generate the raw source file
for object in $schema_objects; do
echo "Processing object ${object}..."
$PYTHON generate_from_schema.py -l "${schemadoc}/json-schema" -t redfish $object -o "gofiles/${object}.go"
$PYTHON generate_from_schema.py -l "${schemadoc}/json-schema" -t redfish "${object}" -o "gofiles/${object}.go"
done

# Then clean them up
Expand Down
59 changes: 19 additions & 40 deletions tools/generate_from_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,15 @@
import logging
import os
import textwrap
import re

import jinja2
import requests

LOG = logging.getLogger(__name__)

REDFISH_SCHEMA_BASE = 'http://redfish.dmtf.org/schemas/v1/'
SWORDFISH_SCHEMA_BASE = 'http://redfish.dmtf.org/schemas/swordfish/v1/'
REDFISH_SCHEMA_BASE = 'https://redfish.dmtf.org/schemas/v1/'
SWORDFISH_SCHEMA_BASE = 'https://redfish.dmtf.org/schemas/swordfish/v1/'

COMMON_NAME_CHANGES = {
'Oem': 'OEM',
Expand All @@ -34,43 +35,13 @@
'Identifier': 'Identifier shall be unique within the managed ecosystem.',
}

# Needed for some invalid variable names
NUMBER_WORDS = {
'1': 'One',
'2': 'Two',
'3': 'Three',
'4': 'Four',
'5': 'Five',
'6': 'Six',
'7': 'Seven',
'8': 'Eight',
'9': 'Nine',
}


def _ident(name):
"""Gets an identifying name that has been cleaned up from the raw name."""
outname = name

# Convert dashes to underscores
outname = outname.replace('-', '_')
# Watch out for keyword switch
outname = outname.replace('switch', 'Switch')
# Collapse spaces
outname = outname.replace(' ', '')
# Replace special characters
outname = outname.replace(':', '_')
outname = outname.replace('/', '_div_')
outname = outname.replace('+', '_plus_')
return re.sub(r'[^a-zA-Z0-9]', r'', name)

if len(outname) == 1:
if outname[0].isdigit():
outname = NUMBER_WORDS.get(outname, "N%s" % outname)

return outname


def _format_comment(name, description, cutpoint='used', add=' is'):
def _format_comment(name, description, cutpoint='shall', add=''):
if name in COMMON_DESC:
return '// %s' % COMMON_DESC[name]

Expand All @@ -86,21 +57,23 @@ def _get_desc(obj):
desc = obj.get('longDescription')
if not desc:
desc = obj.get('description', '')
return desc
return re.sub(r' ', r' ', desc)


def _get_type(name, obj):
result = 'string'
tipe = obj.get('type')
anyof = obj.get('anyOf') or obj.get('items', {}).get('anyOf')
if 'count' in name.lower():
if name.endswith('Count'):
result = 'int'
elif name == 'Status':
result = 'common.Status'
elif name == 'Identifier':
result = 'common.Identifier'
elif name == 'Description':
result = 'string'
elif name == 'UUID':
result = 'string'
elif tipe == 'object':
result = name
elif isinstance(tipe, list):
Expand Down Expand Up @@ -174,7 +147,7 @@ def _add_enum(params, name, enum):
enum_info = {
'name': name,
'identname': _ident(name),
'description': _format_comment(name, _get_desc(enum)),
'description': _format_comment(_ident(name), _get_desc(enum), cutpoint='', add=' is'),
'members': []}

for en in enum.get('enum', []):
Expand All @@ -184,7 +157,7 @@ def _add_enum(params, name, enum):
else:
desc = enum.get('enumDescriptions', {}).get(en, '')
member['description'] = _format_comment(
'%s%s' % (en, name), desc, cutpoint='shall', add='')
'%s%s' % (_ident(en), name), desc, cutpoint='shall', add='')
enum_info['members'].append(member)
params['enums'].append(enum_info)

Expand Down Expand Up @@ -250,6 +223,7 @@ def main():

# Get the most recent versioned schema from the base
version_url = ''
major, minor, errata = 0, 0, 0
for classdef in base_data.get('definitions', []):
if classdef == args.object:
refs = base_data['definitions'][classdef].get('anyOf', [])
Expand All @@ -258,8 +232,13 @@ def main():
if 'idRef' in reflink:
continue
refurl = reflink.split('#')[0]
if refurl > version_url:
version_url = refurl
refver = re.search(r'v(\d+_\d+_\d+)', refurl)
if refver:
ver = refver.group(1).split('_')
mjr, mnr, ert = int(ver[0]), int(ver[1]), int(ver[2])
if mjr > major or mnr > minor or ert > errata:
version_url = refurl
major, minor, errata = mjr, mnr, ert
break

if version_url:
Expand Down
10 changes: 5 additions & 5 deletions tools/source.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,20 @@ import (
type {{ enum.name }} string

const (
{% for enum_member in enum.members %}
{%- for enum_member in enum.members %}
{{ enum_member.description }}
{{ enum_member.identname }}{{ enum.name }} {{ enum.name }} = "{{ enum_member.name }}"
{%- endfor %}
)
{% endfor %}
{%- endfor %}
{% for class in classes -%}

{{ class.description }}
type {{ class.name }} struct {
{% if class.isEntity %}
{%- if class.isEntity %}
common.Entity
{% endif %}
{% for attr in class.attrs %}
{%- endif %}
{%- for attr in class.attrs %}
{{ attr.description }}
{{ attr.name }} {{ attr.type }}
{%- endfor %}
Expand Down

0 comments on commit 5fb1a98

Please sign in to comment.