Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Corrections to subset mode. Addresses #271 #321

Merged
merged 2 commits into from
Nov 2, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion doc-generator/doc_formatter/csv_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ def __init__(self, property_data, traverser, config, level=0):
self.writer.writerow(headings)


def format_property_row(self, schema_ref, prop_name, prop_info, prop_path=[], in_array=False):
def format_property_row(self, schema_ref, prop_name, prop_info, prop_path=[], in_array=False, as_action_parameters=False,
in_schema_ref=None):
"""Format information for a single property.

Returns an object with 'row', 'details', and 'action_details':
Expand Down
62 changes: 44 additions & 18 deletions doc-generator/doc_formatter/doc_formatter.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ def __init__(self, property_data, traverser, config, level=0):
'description', 'longDescription', 'verbatim_description', 'fulldescription_override', 'pattern',
'readonly', 'prop_required', 'prop_required_on_create', 'requiredParameter', 'required_parameter',
'versionAdded', 'versionDeprecated', 'deprecated', 'enumVersionAdded', 'enumVersionDeprecated', 'enumDeprecated',
'translation'
'translation', '_profile'
]


Expand Down Expand Up @@ -257,7 +257,8 @@ def add_registry_reqs(self, registry_reqs):
raise NotImplementedError


def format_property_row(self, schema_ref, prop_name, prop_info, prop_path=[], in_array=False, as_action_parameters=False):
def format_property_row(self, schema_ref, prop_name, prop_info, prop_path=[], in_array=False, as_action_parameters=False,
in_schema_ref=None):
"""Format information for a single property. Returns an object with 'row' and 'details'.

'row': content for the main table being generated.
Expand Down Expand Up @@ -586,6 +587,8 @@ def generate_output(self):
if self.config.get('combine_multiple_refs', 0) > 1:
for prop_name in prop_names:
prop_info = properties[prop_name]
if profile:
prop_info['_profile'] = profile.get('PropertyRequirements', {}.get(prop_name))

# Note: we are calling extend_property_info here solely for the purpose of counting refs.
# In the next loop we call it again to generate the data to format -- we need to get the complete count
Expand All @@ -607,6 +610,9 @@ def generate_output(self):
prop_info['parent_requires'] = required
prop_info['parent_requires_on_create'] = required_on_create
prop_info['required_parameter'] = prop_info.get('requiredParameter')
if profile:
prop_info['_profile'] = profile.get('PropertyRequirements', {}).get(prop_name)

prop_infos = self.extend_property_info(schema_ref, prop_info)
formatted = self.format_property_row(schema_ref, prop_name, prop_infos, [])
if formatted:
Expand Down Expand Up @@ -824,6 +830,8 @@ def extend_property_info(self, schema_ref, prop_info):
outside_ref = None
schema_name = traverser.get_schema_name(schema_ref)

profile = prop_info.get('_profile', None)

excerpt_copy_name = prop_info.get('excerptCopy')
if excerpt_copy_name and excerpt_copy_name.endswith('Excerpt'): # It should.
excerpt_copy_name = excerpt_copy_name[:-7]
Expand Down Expand Up @@ -879,6 +887,7 @@ def extend_property_info(self, schema_ref, prop_info):
prop_name = ref_info.get('_prop_name', False)
is_ref_to_same_schema = ((not is_other_schema) and prop_name == schema_name)
reference_disposition = self.config.get('reference_disposition') and self.config['reference_disposition'].get(prop_ref)
include_per_profile = profile is not None

if is_collection_of and ref_info.get('anyOf'):
anyof_ref = None
Expand All @@ -895,7 +904,7 @@ def extend_property_info(self, schema_ref, prop_info):
if ref_info.get('type') == 'object':
# If this is an excerpt, it will also be an object, and we want to expand-in-place.
# The same applies (or should) if config explicitly says to include:
if excerpt_copy_name or (reference_disposition == 'include'):
if excerpt_copy_name or (reference_disposition == 'include') or include_per_profile:
if is_documented_schema:
excerpt_link = self.link_to_own_schema(from_schema_ref, from_schema_uri)
else: # This is not expected.
Expand Down Expand Up @@ -1263,7 +1272,7 @@ def parse_property_info(self, schema_ref, prop_name, prop_infos, prop_path):
'profile_comparison': None
}

profile = None
profile = fallback_profile = None
# Skip profile data if prop_name is blank -- this is just an additional row of info and
# the "parent" row will have the profile info.
if self.config.get('profile_mode') and prop_name:
Expand All @@ -1272,7 +1281,7 @@ def parse_property_info(self, schema_ref, prop_name, prop_infos, prop_path):
profile_section = 'ActionRequirements'
path_to_prop = prop_path.copy()
path_to_prop.append(prop_name)
profile = self.get_prop_profile(schema_ref, path_to_prop, profile_section)
fallback_profile = self.get_prop_profile(schema_ref, path_to_prop, profile_section)

anyof_details = [self.parse_property_info(schema_ref, prop_name, x, prop_path)
for x in prop_infos]
Expand Down Expand Up @@ -1315,6 +1324,11 @@ def parse_property_info(self, schema_ref, prop_name, prop_infos, prop_path):
parsed['prop_required_on_create'] = details[0]['prop_required_on_create']
parsed['required_parameter'] = details[0].get('requiredParameter') == True

if '_profile' in parsed:
profile = parsed['_profile']
else:
profile = fallback_profile

if profile is not None:
parsed['is_in_profile'] = True
parsed['profile_read_req'] = profile.get('ReadRequirement', 'Mandatory')
Expand Down Expand Up @@ -1353,7 +1367,6 @@ def _parse_single_property_info(self, schema_ref, prop_name, prop_info, prop_pat
"""
traverser = self.traverser

# TODO: should this be true for any path that starts with 'Actions'?
within_action = prop_path == ['Actions']

# type may be a string or a list.
Expand All @@ -1379,7 +1392,9 @@ def _parse_single_property_info(self, schema_ref, prop_name, prop_info, prop_pat
# Skip profile data if prop_name is blank -- this is just an additional row of info and
# the "parent" row will have the profile info.
profile = None
if self.config.get('profile_mode') and prop_name:
if '_profile' in prop_info:
profile = prop_info['_profile']
elif self.config.get('profile_mode') and prop_name: # TODO: unclear if this clause is still needed.
prop_brief_name = prop_name
profile_section = 'PropertyRequirements'
if within_action:
Expand Down Expand Up @@ -1499,6 +1514,10 @@ def _parse_single_property_info(self, schema_ref, prop_name, prop_info, prop_pat
promote_me = False # Special case to replace enclosing array with combined array/simple-type

if isinstance(prop_item, dict):

if '_profile' in prop_info:
prop_item['_profile'] = prop_info['_profile'] # carry through the profile, if present.

if 'type' in prop_item and 'properties' not in prop_item:
prop_items = [prop_item]
collapse_description = True
Expand All @@ -1516,7 +1535,7 @@ def _parse_single_property_info(self, schema_ref, prop_name, prop_info, prop_pat
prop_item['readonly'] = prop_info['readonly']

prop_items = self.extend_property_info(schema_ref, prop_item)
# TODO: maybe capture dups here

if excerpt_copy_name:
excerpt_ref_uri = prop_items[0].get('_ref_uri')
excerpt_schema_ref = prop_items[0].get('_from_schema_ref')
Expand Down Expand Up @@ -1792,27 +1811,32 @@ def format_object_descr(self, schema_ref, prop_info, prop_path=[], is_action=Fal
conditional_details = {}

# If prop_info was extracted from a different schema, it will be present as _from_schema_ref
in_schema_ref = schema_ref
schema_ref = prop_info.get('_from_schema_ref', schema_ref)
schema_name = self.traverser.get_schema_name(schema_ref)
in_schema_name = self.traverser.get_schema_name(in_schema_ref)

required = prop_info.get('required', [])
required_on_create = prop_info.get('requiredOnCreate', [])

parent_requires = prop_info.get('parent_requires', [])
parent_requires_on_create = prop_info.get('parent_requires_on_create', [])

prop_names = patterns = False
prop_names = patterns = profile = False
if len(prop_path) and prop_path[0] == 'Actions':
profile_section = 'ActionRequirements'
else:
profile_section = 'PropertyRequirements'

if properties:

prop_names = [x for x in properties.keys()]

if self.config.get('profile_mode') == 'terse' or self.config.get('profile_mode') == 'subset':
if len(prop_path) and prop_path[0] == 'Actions':
profile_section = 'ActionRequirements'

if '_profile' in prop_info:
profile = prop_info['_profile']
else:
profile_section = 'PropertyRequirements'
profile = self.get_prop_profile(schema_ref, prop_path, profile_section)
profile = self.get_prop_profile(schema_ref, prop_path, profile_section)

if profile:
prop_names = self.filter_props_by_profile(prop_names, profile, parent_requires, is_action)
Expand All @@ -1833,7 +1857,9 @@ def format_object_descr(self, schema_ref, prop_info, prop_path=[], is_action=Fal
base_detail_info['prop_required'] = base_detail_info.get('prop_required') or prop_name in parent_requires
base_detail_info['prop_required_on_create'] = (base_detail_info.get('prop_required_on_create') or
prop_name in parent_requires_on_create)
base_detail_info = self.apply_overrides(base_detail_info, schema_name, prop_name)
base_detail_info = self.apply_overrides(base_detail_info, in_schema_name, prop_name)
if profile:
base_detail_info['_profile'] = profile.get(profile_section, {}).get(prop_name)
detail_info = self.extend_property_info(schema_ref, base_detail_info)

if is_action:
Expand All @@ -1842,7 +1868,7 @@ def format_object_descr(self, schema_ref, prop_info, prop_path=[], is_action=Fal

new_path = prop_path.copy()

formatted = self.format_property_row(schema_ref, prop_name, detail_info, new_path)
formatted = self.format_property_row(schema_ref, prop_name, detail_info, new_path, in_schema_ref=in_schema_ref)
if formatted:
output.append(formatted['row'])
if formatted['details']:
Expand All @@ -1864,7 +1890,7 @@ def format_object_descr(self, schema_ref, prop_info, prop_path=[], is_action=Fal
base_pattern_info['prop_required'] = False
base_pattern_info['prop_required_on_create'] = False

base_pattern_info = self.apply_overrides(base_pattern_info, schema_name, None)
base_pattern_info = self.apply_overrides(base_pattern_info, in_schema_name, None)

# Override the description, if any, with a line describing the pattern.
description = _('Property names follow regular expression pattern "%(pattern)s"') % {'pattern': self.escape_regexp(pattern)}
Expand All @@ -1873,7 +1899,7 @@ def format_object_descr(self, schema_ref, prop_info, prop_path=[], is_action=Fal

pattern_info = self.extend_property_info(schema_ref, base_pattern_info)

formatted = self.format_property_row(schema_ref, prop_name, pattern_info, prop_path)
formatted = self.format_property_row(schema_ref, prop_name, pattern_info, prop_path, in_schema_ref=in_schema_ref)
if formatted:
output.append(formatted['row'])
if formatted['details']:
Expand Down
14 changes: 9 additions & 5 deletions doc-generator/doc_formatter/html_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,8 @@ def __init__(self, property_data, traverser, config, level=0):
</style>
"""

def format_property_row(self, schema_ref, prop_name, prop_info, prop_path=[], in_array=False, as_action_parameters=False):
def format_property_row(self, schema_ref, prop_name, prop_info, prop_path=[], in_array=False, as_action_parameters=False,
in_schema_ref=None):
"""Format information for a single property.

Returns an object with 'row', 'details', 'action_details', and 'profile_conditional_details':
Expand All @@ -171,6 +172,9 @@ def format_property_row(self, schema_ref, prop_name, prop_info, prop_path=[], in
This may include embedded objects with their own properties.
"""

if not in_schema_ref:
in_schema_ref = schema_ref

traverser = self.traverser
formatted = [] # The row itself

Expand Down Expand Up @@ -298,7 +302,7 @@ def format_property_row(self, schema_ref, prop_name, prop_info, prop_path=[], in
# If there are prop_details (enum details), add a note to the description:
if formatted_details['has_direct_prop_details'] and not formatted_details['has_action_details']:
if has_enum:
anchor = schema_ref + '|details|' + prop_name
anchor = in_schema_ref + '|details|' + prop_name
text_descr = (_('For the possible property values, see %(link)s in Property details.') %
{'link': '<a href="#' + anchor + '">' + prop_name + '</a>'})
else:
Expand All @@ -310,7 +314,7 @@ def format_property_row(self, schema_ref, prop_name, prop_info, prop_path=[], in

# If this is an Action with details, add a note to the description:
if formatted_details['has_action_details']:
anchor = schema_ref + '|action_details|' + prop_name
anchor = in_schema_ref + '|action_details|' + prop_name
text_descr = (_('For more information, see the %(link)s section below.') %
{'link': '<a href="#' + anchor + '">' + _('Actions') + '</a>'})
formatted_details['descr'] += '<br>' + self.formatter.italic(text_descr)
Expand Down Expand Up @@ -374,7 +378,7 @@ def format_property_row(self, schema_ref, prop_name, prop_info, prop_path=[], in
# Conditional Requirements
cond_req = formatted_details['profile_conditional_req']
if cond_req:
anchor = schema_ref + '|conditional_reqs|' + prop_name
anchor = in_schema_ref + '|conditional_reqs|' + prop_name
cond_req_text = (_('See %(link)s, below, for more information.') %
{'link': '<a href="#' + anchor + '">' + _('Conditional Requirements') + '</a>'})
descr += ' ' + self.formatter.nobr(self.formatter.italic(cond_req_text))
Expand All @@ -386,7 +390,7 @@ def format_property_row(self, schema_ref, prop_name, prop_info, prop_path=[], in
# Comparison
if formatted_details['profile_values']:
comparison_descr = (_('Must be %(comparison_word)s (%(values)s)') %
{'comparison_words': formatted_details['profile_comparison'],
{'comparison_word': formatted_details['profile_comparison'],
'values': ', '.join('"' + x + '"' for x in formatted_details['profile_values'])})
profile_access += '<br>' + self.formatter.italic(comparison_descr)

Expand Down
3 changes: 2 additions & 1 deletion doc-generator/doc_formatter/markdown_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ def __init__(self, property_data, traverser, config, level=0):
self.format_head_four = self.formatter.head_three


def format_property_row(self, schema_ref, prop_name, prop_info, prop_path=[], in_array=False, as_action_parameters=False):
def format_property_row(self, schema_ref, prop_name, prop_info, prop_path=[], in_array=False, as_action_parameters=False,
in_schema_ref=None):
"""Format information for a single property.

Returns an object with 'row', 'details', 'action_details', and 'profile_conditional_details':
Expand Down
3 changes: 2 additions & 1 deletion doc-generator/doc_formatter/property_index_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,8 @@ def add_section(self, text, link_id=False, schema_ref=False):
}


def format_property_row(self, schema_ref, prop_name, prop_info, prop_path=[], in_array=False):
def format_property_row(self, schema_ref, prop_name, prop_info, prop_path=[], in_array=False, as_action_parameters=False,
in_schema_ref=None):
""" Instead of formatting this data, add info to self.properties_by_name. """

if not prop_name:
Expand Down
6 changes: 6 additions & 0 deletions doc-generator/doc_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,12 @@ def simple_warning_format(message, category, filename, lineno, file=None, line=N
profile_resources = self.merge_dicts(profile_merged.get('Resources', {}),
self.config.get('profile', {}).get('Resources', {}))

# Warn the user if a profile specifies items in selected schemas that "don't make sense":
for schema_name in ['IPAddresses', 'Redundancy', 'Resource', 'Settings']:
if schema_name in profile_resources:
warnings.warn('Profiles should not specify requirements directly on the "%(name)s" schema.' %
{'name': schema_name})

if config['profile_mode'] != 'subset':
profile_protocol = self.merge_dicts(profile_merged.get('Protocol', {}),
self.config.get('profile', {}).get('Protocol', {}))
Expand Down
2 changes: 1 addition & 1 deletion doc-generator/locale/doc_generator.pot
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: 2020-10-26 12:16-0700\n"
"POT-Creation-Date: 2020-10-26 16:51-0700\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <[email protected]>\n"
Expand Down
Binary file modified doc-generator/locale/en/LC_MESSAGES/doc_generator.mo
Binary file not shown.
2 changes: 1 addition & 1 deletion doc-generator/locale/en/LC_MESSAGES/doc_generator.po
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: 2020-10-26 12:16-0700\n"
"POT-Creation-Date: 2020-10-26 16:51-0700\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <[email protected]>\n"
Expand Down
Loading