From 22485e82b1e4c3be2f7589434d53c75b28921266 Mon Sep 17 00:00:00 2001
From: Dan Lee <71398022+dandhlee@users.noreply.github.com>
Date: Fri, 30 Jul 2021 11:41:40 -0400
Subject: [PATCH] fix: parse xrefs differently with new xref format (#90)
* fix: parse xrefs differently with new xref format
* fix: update Docstring parser
* test: update unit test
* fix: move error catching to another block
* test: update unittest to include error scenarios
* fix: clean up messy formatting
---
docfx_yaml/extension.py | 49 ++++++++++++++++++++++++++++++-----------
tests/test_unit.py | 25 ++++++++++++++-------
2 files changed, 53 insertions(+), 21 deletions(-)
diff --git a/docfx_yaml/extension.py b/docfx_yaml/extension.py
index d0e8316c..6b9b6496 100644
--- a/docfx_yaml/extension.py
+++ b/docfx_yaml/extension.py
@@ -327,24 +327,37 @@ def _extract_docstring_info(summary_info, summary, name):
}
initial_index = -1
+ front_tag = '"
- while "text"
+ while front_tag in summary_part:
- # Expecting format of ":"
- if "'))+1]
+ # Expecting format of "text"
+ if front_tag in summary_part:
+ # Retrieve the index for starting position of xref tag
+ initial_index += summary_part.find(front_tag)
+
+ # Find the index of the end of xref tag, relative to the start of xref tag
+ end_tag_index = initial_index + parsed_text[initial_index:].find(end_tag) + end_len
+
+ # Retrieve the entire xref tag
+ original_type = parsed_text[initial_index:end_tag_index]
initial_index += len(original_type)
original_type = " ".join(filter(None, re.split(r'\n| |\|\s|\t', original_type)))
- safe_type = 'xref_' + original_type[6:-1]
+
+ # Extract text from "text"
+ index = original_type.find(">")
+ safe_type = 'xref_' + original_type[index+1:index+(original_type[index:].find("<"))]
else:
raise ValueError("Encountered unexpected type in Exception docstring.")
@@ -451,10 +464,20 @@ def _extract_docstring_info(summary_info, summary, name):
cur_type = word
if cur_type in [':type', ':param', ':raises', ':raises:']:
index += 1
- arg_name = parsed_text[index][:-1]
- # Initialize empty dictionary if it doesn't exist already
- if arg_name not in summary_info[var_types[cur_type]] and ':raises' not in cur_type:
- summary_info[var_types[cur_type]][arg_name] = {}
+ # Exception that's not xref should be treated same as other names
+ if ':raises' not in cur_type or 'xref' not in parsed_text[index]:
+ arg_name = parsed_text[index][:-1]
+ # xrefs are treated by taking its second half and combining the two
+ elif ':raises' in cur_type and 'xref' in parsed_text[index]:
+ arg_name = f'{parsed_text[index]} {parsed_text[index+1][:-1]}'
+ index += 1
+
+ try:
+ # Initialize empty dictionary if it doesn't exist already
+ if arg_name not in summary_info[var_types[cur_type]] and ':raises' not in cur_type:
+ summary_info[var_types[cur_type]][arg_name] = {}
+ except KeyError:
+ raise KeyError(f"Encountered wrong formatting, please check docstring for {name}")
# Empty target string
words = []
diff --git a/tests/test_unit.py b/tests/test_unit.py
index 1353f56f..7d11bdde 100644
--- a/tests/test_unit.py
+++ b/tests/test_unit.py
@@ -335,13 +335,22 @@ def test_extract_docstring_info_check_error(self):
with self.assertRaises(ValueError):
_extract_docstring_info({}, summary4, "error string")
+ summary5 = """
+Description of malformed docstring.
+
+Raises:
+ Error that should fail: if condition `x`.
+"""
+ with self.assertRaises(KeyError):
+ _extract_docstring_info({}, summary5, "malformed docstring")
+
def test_extract_docstring_info_with_xref(self):
## Test with xref included in the summary, ensure they're processed as-is
summary_info_want = {
'variables': {
'arg1': {
- 'var_type': '',
+ 'var_type': 'Type',
'description': 'simple description.'
},
'arg2': {
@@ -351,13 +360,13 @@ def test_extract_docstring_info_with_xref(self):
},
'returns': [
{
- 'var_type': '',
+ 'var_type': 'Pair',
'description': 'simple description for return value.'
}
],
'exceptions': [
{
- 'var_type': '',
+ 'var_type': 'SpannerException',
'description': 'if `condition x`.'
}
]
@@ -366,15 +375,15 @@ def test_extract_docstring_info_with_xref(self):
summary = """
Simple test for docstring.
-:type arg1:
+:type arg1: Type
:param arg1: simple description.
:param arg2: simple description for `arg2`.
:type arg2: ~google.spanner_v1.type.dict
-:rtype:
+:rtype: Pair
:returns: simple description for return value.
-:raises : if `condition x`.
+:raises SpannerException: if `condition x`.
"""
summary_info_got = {
@@ -384,10 +393,10 @@ def test_extract_docstring_info_with_xref(self):
}
top_summary_got = _extract_docstring_info(summary_info_got, summary, "")
-
+ self.maxDiff = None
# Same as the top summary from previous example, compare with that
self.assertEqual(top_summary_got, self.top_summary1_want)
- self.assertEqual(summary_info_got, summary_info_want)
+ self.assertDictEqual(summary_info_got, summary_info_want)
if __name__ == '__main__':
unittest.main()