From b8fa93ec17949b92bc0d7286767fa8213cfbaf3d Mon Sep 17 00:00:00 2001 From: Dan Lee <71398022+dandhlee@users.noreply.github.com> Date: Fri, 3 May 2024 20:23:57 -0400 Subject: [PATCH] test: refactor unit_test.py (#377) * test: refactor upto references * tests: refactor docstring extractor * tests: refactor upto packages * test: refactors for parsing docstring summary * tests: finished refactoring test_unit.py * test: update typos * test: move the explanation comment up * test: refactor to use test paramters * test: refactor rest of tests into similar format --- tests/test_unit.py | 1342 ++++++++++++++++++++++++++------------------ 1 file changed, 799 insertions(+), 543 deletions(-) diff --git a/tests/test_unit.py b/tests/test_unit.py index ce5870bb..4ab3b3a0 100644 --- a/tests/test_unit.py +++ b/tests/test_unit.py @@ -6,68 +6,77 @@ from yaml import load, Loader class TestGenerate(unittest.TestCase): - def test_find_unique_name(self): + def test_finds_unique_name(self): entries = {} # Disambiguate with unique entries. - entry1 = "google.cloud.aiplatform.v1.schema.predict.instance_v1.types" - entry2 = "google.cloud.aiplatform.v1beta2.schema.predict.instance_v1.types" - want1 = "v1.types" - want2 = "v1beta2.types" - - for entry in [entry1, entry2]: + schema_v1_entry = ( + "google.cloud.aiplatform.v1.schema.predict.instance_v1.types" + ) + schema_v1beta2_entry = ( + "google.cloud.aiplatform.v1beta2.schema.predict.instance_v1.types" + ) + for entry in [schema_v1_entry, schema_v1beta2_entry]: for word in entry.split("."): if word not in entries: entries[word] = 1 else: entries[word] += 1 - got1 = extension.find_unique_name(entry1.split("."), entries) - got2 = extension.find_unique_name(entry2.split("."), entries) - - self.assertEqual(want1, ".".join(got1)) - self.assertEqual(want2, ".".join(got2)) - - - def test_disambiguate_toc_name(self): - - with open('tests/yaml_post.yaml', 'r') as want_file: - yaml_want = load(want_file, Loader=Loader) - disambiguated_names_want = { - 'google.cloud.spanner_admin_database_v1.types': 'spanner_admin_database_v1.types', - 'google.cloud.spanner_admin_instance_v1.types': 'spanner_admin_instance_v1.types', - 'google.cloud.spanner_v1.types': 'spanner_v1.types' - } - - with open('tests/yaml_pre.yaml', 'r') as test_file: - yaml_got = load(test_file, Loader=Loader) - disambiguated_names_got = extension.disambiguate_toc_name(yaml_got) - - self.assertEqual(yaml_want, yaml_got) - self.assertEqual(disambiguated_names_want, disambiguated_names_got) - - - def test_disambiguate_toc_name_duplicate(self): - - with open('tests/yaml_post_duplicate.yaml', 'r') as want_file: - yaml_want = load(want_file, Loader=Loader) - disambiguated_names_want = { - 'google.api_core.client_info': 'client_info', - 'google.api_core.gapic_v1.client_info': 'gapic_v1.client_info' - } + unique_v1_name = extension.find_unique_name( + schema_v1_entry.split("."), entries + ) + unique_v1beta2_name = extension.find_unique_name( + schema_v1beta2_entry.split("."), entries + ) - with open('tests/yaml_pre_duplicate.yaml', 'r') as test_file: - yaml_got = load(test_file, Loader=Loader) - disambiguated_names_got = extension.disambiguate_toc_name(yaml_got) + self.assertEqual("v1.types", ".".join(unique_v1_name)) + self.assertEqual("v1beta2.types", ".".join(unique_v1beta2_name)) - self.assertEqual(yaml_want, yaml_got) - self.assertEqual(disambiguated_names_want, disambiguated_names_got) + test_entries = [ + [ + "tests/yaml_pre.yaml", + "tests/yaml_post.yaml", + { + "google.cloud.spanner_admin_database_v1.types": "spanner_admin_database_v1.types", + "google.cloud.spanner_admin_instance_v1.types": "spanner_admin_instance_v1.types", + "google.cloud.spanner_v1.types": "spanner_v1.types", + }, + ], + [ + # Tests duplicate names + "tests/yaml_pre_duplicate.yaml", + "tests/yaml_post_duplicate.yaml", + { + "google.api_core.client_info": "client_info", + "google.api_core.gapic_v1.client_info": "gapic_v1.client_info", + }, + ] + ] + @parameterized.expand(test_entries) + def test_disambiguates_toc_name( + self, + test_filename, + expected_filename, + expected_disambiguated_names, + ): + with open(test_filename, "r") as test_file: + test_yaml = load(test_file, Loader=Loader) + with open(expected_filename, "r") as expected_yaml_file: + expected_yaml = load(expected_yaml_file, Loader=Loader) + + disambiguated_names = extension.disambiguate_toc_name( + test_yaml + ) + self.assertEqual(expected_yaml, test_yaml) + self.assertEqual(expected_disambiguated_names, disambiguated_names) - def test_reference_in_summary(self): - lines_got = """ + test_entries = [ + [ + """ If a ``stream`` is attached to this download, then the downloaded resource will be written to the stream. @@ -87,22 +96,12 @@ def test_reference_in_summary(self): ~google.cloud.requests.Response: The HTTP response returned by ``transport``. Raises: - ~google.cloud.resumable_media.common.DataCorruption: If the download's + ~google.cloud.resumable_media.common.DataCorruption: If the download"s checksum doesn't agree with server-computed checksum. ValueError: If the current :class:`Download` has already finished. -""" - lines_got = lines_got.split("\n") - xrefs_got = [] - # Resolve over different regular expressions for different types of reference patterns. - lines_got, xrefs = extension._resolve_reference_in_module_summary(extension.REF_PATTERN, lines_got) - for xref in xrefs: - xrefs_got.append(xref) - lines_got, xrefs = extension._resolve_reference_in_module_summary(extension.REF_PATTERN_LAST, lines_got) - for xref in xrefs: - xrefs_got.append(xref) - - lines_want = """ + """, + """ If a ``stream`` is attached to this download, then the downloaded resource will be written to the stream. @@ -122,28 +121,20 @@ def test_reference_in_summary(self): Response: The HTTP response returned by ``transport``. Raises: - DataCorruption: If the download's + DataCorruption: If the download"s checksum doesn't agree with server-computed checksum. ValueError: If the current `Download` has already finished. -""" - lines_want = lines_want.split("\n") - xrefs_want = [ - "google.cloud.requests.Session", - "google.cloud.requests.Session.request", - "google.cloud.requests.Response", - "google.cloud.resumable_media.common.DataCorruption" - ] - - self.assertEqual(lines_got, lines_want) - self.assertCountEqual(xrefs_got, xrefs_want) - # assertCountEqual is a misleading name but checks that two lists contain - # same items regardless of order, as long as items in list are sortable. - - - # Test for added xref coverage and third party xrefs staying as-is - def test_reference_in_summary_more_xrefs(self): - lines_got = """ + """, + [ + "google.cloud.requests.Session", + "google.cloud.requests.Session.request", + "google.cloud.requests.Response", + "google.cloud.resumable_media.common.DataCorruption", + ], + ], + [ + """ If a ~dateutil.time.stream() is attached to this download, then the downloaded resource will be written to the stream. @@ -158,18 +149,8 @@ def test_reference_in_summary_more_xrefs(self): Can also be passed as a :func:`~google.cloud.requests.tuple()` (connect_timeout, read_timeout). See :meth:`google.cloud.requests.Session.request()` documentation for details. -""" - lines_got = lines_got.split("\n") - xrefs_got = [] - # Resolve over different regular expressions for different types of reference patterns. - lines_got, xrefs = extension._resolve_reference_in_module_summary(extension.REF_PATTERN, lines_got) - for xref in xrefs: - xrefs_got.append(xref) - lines_got, xrefs = extension._resolve_reference_in_module_summary(extension.REF_PATTERN_LAST, lines_got) - for xref in xrefs: - xrefs_got.append(xref) - - lines_want = """ + """, + """ If a `dateutil.time.stream()` is attached to this download, then the downloaded resource will be written to the stream. @@ -184,92 +165,91 @@ def test_reference_in_summary_more_xrefs(self): Can also be passed as a tuple() (connect_timeout, read_timeout). See request() documentation for details. -""" - lines_want = lines_want.split("\n") - xrefs_want = [ - "google.cloud.requests.Session", - "google.cloud.requests.tuple", - "google.cloud.requests.Session.request" - ] - - self.assertEqual(lines_got, lines_want) - self.assertCountEqual(xrefs_got, xrefs_want) - # assertCountEqual is a misleading name but checks that two lists contain - # same items regardless of order, as long as items in list are sortable. - - - # Variables used for testing _extract_docstring_info - top_summary1_want = "\nSimple test for docstring.\n\n" - summary_info1_want = { - 'variables': { - 'arg1': { - 'var_type': 'int', - 'description': 'simple description.' - }, - 'arg2': { - 'var_type': 'str', - 'description': 'simple description for `arg2`.' - } - }, - 'returns': [ - { - 'var_type': 'str', - 'description': 'simple description for return value.' - } + """, + [ + "google.cloud.requests.Session", + "google.cloud.requests.tuple", + "google.cloud.requests.Session.request", + ], ], - 'exceptions': [ - { - 'var_type': 'AttributeError', - 'description': 'if `condition x`.' - } - ] - } - + ] + @parameterized.expand(test_entries) + def test_resolves_references_in_summary( + self, + test_docstring, + expected_content, + expected_xrefs, + ): + xrefs_to_check = [] + # Resolve over different regular expressions for different types of reference patterns. + content_to_resolve, xrefs = ( + extension._resolve_reference_in_module_summary( + extension.REF_PATTERN, + test_docstring.split("\n"), + ) + ) + xrefs_to_check.extend(xrefs) - # Test for resolving square bracketed references. - def test_reference_square_brackets(self): - xrefs_want = [ - 'google.cloud.kms.v1.KeyRing.name', - 'google.cloud.kms.v1.KeyRing', - 'google.cloud.kms.v1.ImportJob', - ] - summary_want = """Required. + resolved_content, xrefs = ( + extension._resolve_reference_in_module_summary( + extension.REF_PATTERN_LAST, + content_to_resolve, + ) + ) + xrefs_to_check.extend(xrefs) -The name of the KeyRing associated with the ImportJobs. -""" - summary_want = summary_want.split("\n") + self.assertEqual(resolved_content, expected_content.split("\n")) + self.assertCountEqual(xrefs_to_check, expected_xrefs) - summary = """Required. + test_entries = [ + [ + """Required. The [name][google.cloud.kms.v1.KeyRing.name] of the [KeyRing][google.cloud.kms.v1.KeyRing] associated with the [ImportJobs][google.cloud.kms.v1.ImportJob]. -""" - summary = summary.split("\n") + """, + """Required. - summary_got, xrefs_got = extension._resolve_reference_in_module_summary(extension.REF_PATTERN_BRACKETS, summary) +The name of the KeyRing associated with the ImportJobs. + """, + [ + "google.cloud.kms.v1.KeyRing.name", + "google.cloud.kms.v1.KeyRing", + "google.cloud.kms.v1.ImportJob", + ], + ], + ] + @parameterized.expand(test_entries) + def test_resolves_square_bracket_references( + self, + summary, + expected_summary, + expected_xrefs, + ): + resolved_summary, xrefs = ( + extension._resolve_reference_in_module_summary( + extension.REF_PATTERN_BRACKETS, + summary.split("\n"), + ) + ) - self.assertEqual(summary_got, summary_want) - self.assertCountEqual(xrefs_got, xrefs_want) + self.assertEqual(resolved_summary, expected_summary.split("\n")) + self.assertCountEqual(xrefs, expected_xrefs) - # Check that other patterns throws an exception. - def test_reference_check_error(self): + def test_raises_error_for_invalid_references(self): with self.assertRaises(ValueError): - extension._resolve_reference_in_module_summary('.*', 'not a valid ref line'.split('\n')) - - - def test_extract_docstring_info_normal_input(self): + extension._resolve_reference_in_module_summary( + ".*", + "not a valid ref line".split("\n"), + ) - ## Test for normal input - summary_info1_got = { - 'variables': {}, - 'returns': [], - 'exceptions': [] - } - summary1 = """ + test_entries = [ + [ + """ Simple test for docstring. -Args: +Args: arg1(int): simple description. arg2(str): simple description for `arg2`. @@ -278,17 +258,32 @@ def test_extract_docstring_info_normal_input(self): Raises: AttributeError: if `condition x`. -""" - - top_summary1_got = extension._extract_docstring_info(summary_info1_got, summary1, "") - - self.assertEqual(top_summary1_got, self.top_summary1_want) - self.assertEqual(summary_info1_got, self.summary_info1_want) - - - def test_extract_docstring_info_mixed_format(self): - ## Test for input coming in mixed format. - summary2 = """ + """, + "\nSimple test for docstring.\n\n", + { + "variables": { + "arg1": { + "var_type": "int", + "description": "simple description.", + }, + "arg2": { + "var_type": "str", + "description": "simple description for `arg2`.", + }, + }, + "returns": [{ + "var_type": "str", + "description": "simple description for return value.", + }], + "exceptions": [{ + "var_type": "AttributeError", + "description": "if `condition x`.", + }], + }, + ], + [ + # Tests summary in mixed format + """ Simple test for docstring. :type arg1: int @@ -299,102 +294,58 @@ def test_extract_docstring_info_mixed_format(self): :rtype: str :returns: simple description for return value. -:raises AttributeError: if `condition x`. -""" - - summary_info2_got = { - 'variables': {}, - 'returns': [], - 'exceptions': [] - } - - top_summary2_got = extension._extract_docstring_info(summary_info2_got, summary2, "") - - # Output should be same as test 1 with normal input. - self.assertEqual(top_summary2_got, self.top_summary1_want) - self.assertEqual(summary_info2_got, self.summary_info1_want) - - - def test_extract_docstring_info_check_parser(self): - ## Test for parser to correctly scan docstring tokens and not custom fields - summary_info3_want = { - 'variables': {}, - 'returns': [], - 'exceptions': [] - } +:raises AttributeError: if `condition x`. + """, + "\nSimple test for docstring.\n\n", + { + "variables": { + "arg1": { + "var_type": "int", + "description": "simple description.", + }, + "arg2": { + "var_type": "str", + "description": "simple description for `arg2`.", + }, + }, + "returns": [{ + "var_type": "str", + "description": "simple description for return value.", + }], + "exceptions": [{ + "var_type": "AttributeError", + "description": "if `condition x`.", + }], + }, - summary3 = """ + ], + [ + # Tests summary for docstring tokens and not custom fields + """ Union[int, None]: Expiration time in milliseconds for a partition. If :attr:`partition_expiration` is set and is not set, :attr:`type_` will default to :attr:`~google.cloud.bigquery.table.TimePartitioningType.DAY`. It could return :param: with :returns as well. -""" - - summary_info3_got = { - 'variables': {}, - 'returns': [], - 'exceptions': [] - } - - # Nothing should change - top_summary3_want = summary3 - - top_summary3_got = extension._extract_docstring_info(summary_info3_got, summary3, "") - - self.assertEqual(top_summary3_got, top_summary3_want) - self.assertEqual(summary_info3_got, summary_info3_want) - - - def test_extract_docstring_info_check_error(self): - ## Test for incorrectly formmatted docstring raising error - summary4 = """ -Description of docstring which should fail. - -:returns:param: -""" - with self.assertRaises(ValueError): - extension._extract_docstring_info({}, summary4, "error string") - - summary5 = """ -Description of malformed docstring. - -Raises: - Error that should fail: if condition `x`. -""" - with self.assertRaises(KeyError): - extension._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': 'Type', - 'description': 'simple description.' - }, - 'arg2': { - 'var_type': '~google.spanner_v1.type.dict', - 'description': 'simple description for `arg2`.' - } - }, - 'returns': [ - { - 'var_type': 'Pair', - 'description': 'simple description for return value.' - } - ], - 'exceptions': [ - { - 'var_type': 'SpannerException', - 'description': 'if `condition x`.' - } - ] - } + """, + """ +Union[int, None]: Expiration time in milliseconds for a partition. - summary = """ +If :attr:`partition_expiration` is set and is +not set, :attr:`type_` will default to +:attr:`~google.cloud.bigquery.table.TimePartitioningType.DAY`. +It could return :param: with :returns as well. + """, + { + "variables": {}, + "returns": [], + "exceptions": [], + } + ], + [ + # Tests summary with xrefs + """ Simple test for docstring. :type arg1: Type @@ -405,25 +356,34 @@ def test_extract_docstring_info_with_xref(self): :rtype: Pair :returns: simple description for return value. -:raises SpannerException: if `condition x`. -""" - - summary_info_got = { - 'variables': {}, - 'returns': [], - 'exceptions': [] - } - - top_summary_got = extension._extract_docstring_info(summary_info_got, summary, "") - # Same as the top summary from previous example, compare with that - self.assertEqual(top_summary_got, self.top_summary1_want) - self.assertDictEqual(summary_info_got, summary_info_want) - - - def test_extract_docstring_info_no_summary(self): - ## Test parsing docstring with no summary. - summary =( -"""Args: +:raises SpannerException: if `condition x`. + """, + "\nSimple test for docstring.\n\n", + { + "variables": { + "arg1": { + "var_type": "Type", + "description": "simple description.", + }, + "arg2": { + "var_type": "~google.spanner_v1.type.dict", + "description": "simple description for `arg2`.", + }, + }, + "returns": [{ + "var_type": "Pair", + "description": "simple description for return value.", + }], + "exceptions": [{ + "var_type": "SpannerException", + "description": "if `condition x`.", + }], + }, + ], + [ + # Tests docstring without a summary + """ +Args: arg1(int): simple description. arg2(str): simple description for `arg2`. @@ -432,101 +392,124 @@ def test_extract_docstring_info_no_summary(self): Raises: AttributeError: if `condition x`. -""" - ) - summary_info_got = { - 'variables': {}, - 'returns': [], - 'exceptions': [] - } - - top_summary_got = extension._extract_docstring_info(summary_info_got, summary, "") - self.assertEqual(top_summary_got, "") - self.assertDictEqual(summary_info_got, self.summary_info1_want) - - - def test_find_package_group(self): - package_group_want = "google.cloud.spanner_v1beta2" - uid = "google.cloud.spanner_v1beta2.services.admin_database_v1.types" + """, + "\n", + { + "variables": { + "arg1": { + "var_type": "int", + "description": "simple description.", + }, + "arg2": { + "var_type": "str", + "description": "simple description for `arg2`.", + }, + }, + "returns": [{ + "var_type": "str", + "description": "simple description for return value.", + }], + "exceptions": [{ + "var_type": "AttributeError", + "description": "if `condition x`.", + }], + }, - package_group_got = extension.find_package_group(uid) - self.assertEqual(package_group_got, package_group_want) + ], + ] + @parameterized.expand(test_entries) + def test_extracts_docstring_info( + self, + summary, + expected_top_summary, + expected_summary_info + ): + summary_info = { + "variables": {}, + "returns": [], + "exceptions": [] + } + top_summary = extension._extract_docstring_info( + summary_info, + summary, + "", + ) - def test_pretty_package_name(self): - package_name_want = "Spanner V1beta2" - package_group = "google.cloud.spanner_v1beta2" + self.assertEqual(top_summary, expected_top_summary) + self.assertDictEqual(summary_info, expected_summary_info) - package_name_got = extension.pretty_package_name(package_group) - self.assertEqual(package_name_got, package_name_want) + test_entries = [ + [ + """ +Description of docstring which should fail. - def test_group_by_package(self): - toc_yaml_want = [ - { - "name": "Spanner Admin Database V1", - "uidname":"google.cloud.spanner_admin_database_v1", - "items": [ - { - "name":"database_admin", - "uidname":"google.cloud.spanner_admin_database_v1.services.database_admin", - "items":[ - { - "name":"Overview", - "uidname":"google.cloud.spanner_admin_database_v1.services.database_admin", - "uid":"google.cloud.spanner_admin_database_v1.services.database_admin" - }, - { - "name":"ListBackupOperationsAsyncPager", - "uidname":"google.cloud.spanner_admin_database_v1.services.database_admin.pagers.ListBackupOperationsAsyncPager", - "uid":"google.cloud.spanner_admin_database_v1.services.database_admin.pagers.ListBackupOperationsAsyncPager" - } - ] - }, - { - "name":"spanner_admin_database_v1.types", - "uidname":"google.cloud.spanner_admin_database_v1.types", - "items":[ - { - "name":"Overview", - "uidname":"google.cloud.spanner_admin_database_v1.types", - "uid":"google.cloud.spanner_admin_database_v1.types" - }, - { - "name":"BackupInfo", - "uidname":"google.cloud.spanner_admin_database_v1.types.BackupInfo", - "uid":"google.cloud.spanner_admin_database_v1.types.BackupInfo" - } - ] - }, - ] - }, - { - "name": "Spanner V1", - "uidname":"google.cloud.spanner_v1", - "items": [ - { - "name":"pool", - "uidname":"google.cloud.spanner_v1.pool", - "items":[ - { - "name":"Overview", - "uidname":"google.cloud.spanner_v1.pool", - "uid":"google.cloud.spanner_v1.pool" - }, - { - "name":"AbstractSessionPool", - "uidname":"google.cloud.spanner_v1.pool.AbstractSessionPool", - "uid":"google.cloud.spanner_v1.pool.AbstractSessionPool" - } - ] - } - ] - } - ] +:returns:param: + """, + ValueError, + "Error string", + ], + [ + """ +Description of malformed docstring. - toc_yaml = [ - { +Raises: + Error that should fail: if condition `x`. + """, + KeyError, + "Malformed docstring", + ], + ] + @parameterized.expand(test_entries) + def test_raises_error_extracting_malformed_docstring( + self, + summary, + error_type, + error_string, + ): + with self.assertRaises(error_type): + extension._extract_docstring_info({}, summary, error_string) + + + test_entries = [ + [ + "google.cloud.spanner_v1beta2.services.admin_database_v1.types", + "google.cloud.spanner_v1beta2", + ], + ] + @parameterized.expand(test_entries) + def test_finds_package_group( + self, + uid, + expected_package_group, + ): + package_group = extension.find_package_group(uid) + + self.assertEqual(package_group, expected_package_group) + + + test_entries = [ + [ + "google.cloud.spanner_v1beta2", + "Spanner V1beta2", + ], + ] + @parameterized.expand(test_entries) + def test_finds_pretty_package_name( + self, + package_group, + expected_package_name, + ): + package_name = extension.pretty_package_name(package_group) + + self.assertEqual(package_name, expected_package_name) + + + test_entries = [ + [ + # toc_yaml entry + [{ "name":"database_admin", "uidname":"google.cloud.spanner_admin_database_v1.services.database_admin", "items":[ @@ -573,18 +556,105 @@ def test_group_by_package(self): "uid":"google.cloud.spanner_v1.pool.AbstractSessionPool" } ] - } - ] + }], + # expected_toc_yaml entry + [ + { + "name": "Spanner Admin Database V1", + "uidname":"google.cloud.spanner_admin_database_v1", + "items": [{ + "name":"database_admin", + "uidname":"google.cloud.spanner_admin_database_v1.services.database_admin", + "items": [{ + "name":"Overview", + "uidname":"google.cloud.spanner_admin_database_v1.services.database_admin", + "uid":"google.cloud.spanner_admin_database_v1.services.database_admin" + }, + { + "name":"ListBackupOperationsAsyncPager", + "uidname":"google.cloud.spanner_admin_database_v1.services.database_admin.pagers.ListBackupOperationsAsyncPager", + "uid":"google.cloud.spanner_admin_database_v1.services.database_admin.pagers.ListBackupOperationsAsyncPager", + }], + }, + { + "name":"spanner_admin_database_v1.types", + "uidname":"google.cloud.spanner_admin_database_v1.types", + "items": [{ + "name":"Overview", + "uidname":"google.cloud.spanner_admin_database_v1.types", + "uid":"google.cloud.spanner_admin_database_v1.types", + }, + { + "name":"BackupInfo", + "uidname":"google.cloud.spanner_admin_database_v1.types.BackupInfo", + "uid":"google.cloud.spanner_admin_database_v1.types.BackupInfo", + }], + }], + }, + { + "name": "Spanner V1", + "uidname":"google.cloud.spanner_v1", + "items": [{ + "name":"pool", + "uidname":"google.cloud.spanner_v1.pool", + "items": [{ + "name":"Overview", + "uidname":"google.cloud.spanner_v1.pool", + "uid":"google.cloud.spanner_v1.pool" + }, + { + "name":"AbstractSessionPool", + "uidname":"google.cloud.spanner_v1.pool.AbstractSessionPool", + "uid":"google.cloud.spanner_v1.pool.AbstractSessionPool", + }], + }], + }, + ], + ], + ] + @parameterized.expand(test_entries) + def test_groups_by_package( + self, + toc_yaml, + expected_toc_yaml, + ): + toc_yaml = extension.group_by_package(toc_yaml) + + self.assertCountEqual(toc_yaml, expected_toc_yaml) - toc_yaml_got = extension.group_by_package(toc_yaml) - self.assertCountEqual(toc_yaml_got, toc_yaml_want) + test_entries = [ + [ + (\ +""" + +.. code-block:: python - def test_parse_docstring_summary(self): - # Check that the summary gets parsed correctly. - attributes_want = [] - summary_want = \ +\n from google.api_core.client_options import ClientOptions +\n from google.cloud.vision_v1 import ImageAnnotatorClient +\n def get_client_cert(): +\n # code to load client certificate and private key. +\n return client_cert_bytes, client_private_key_bytes +\n options = ClientOptions(api_endpoint=\"foo.googleapis.com\", +\n client_cert_source=get_client_cert) +\n client = ImageAnnotatorClient(client_options=options) + + +You can also pass a mapping object. + + +\n.. code-block:: ruby + +\n from google.cloud.vision_v1 import ImageAnnotatorClient +\n client = ImageAnnotatorClient( +\n client_options={ +\n \"api_endpoint\": \"foo.googleapis.com\", +\n \"client_cert_source\" : get_client_cert +\n }) +""" + ), + (\ """```python from google.api_core.client_options import ClientOptions @@ -620,68 +690,45 @@ def get_client_cert(): ``` """ - summary = \ + ), + ], + [ + # Check that nothing changes for literalincludes. + (\ """ +.. literalinclude:: + note that these are not supported yet, so they will be ignored for now. - -.. code-block:: python - -\n from google.api_core.client_options import ClientOptions -\n from google.cloud.vision_v1 import ImageAnnotatorClient -\n def get_client_cert(): -\n # code to load client certificate and private key. -\n return client_cert_bytes, client_private_key_bytes -\n options = ClientOptions(api_endpoint=\"foo.googleapis.com\", -\n client_cert_source=get_client_cert) -\n client = ImageAnnotatorClient(client_options=options) - - -You can also pass a mapping object. - - -\n.. code-block:: ruby - -\n from google.cloud.vision_v1 import ImageAnnotatorClient -\n client = ImageAnnotatorClient( -\n client_options={ -\n \"api_endpoint\": \"foo.googleapis.com\", -\n \"client_cert_source\" : get_client_cert -\n }) +And any other documentation that the source code would have could go here. """ - summary_got, attributes_got = extension._parse_docstring_summary(summary) - self.assertEqual(summary_got, summary_want) - self.assertEqual(attributes_got, attributes_want) - - # Check that nothing much changes otherwise. - summary = \ + ), + (\ """ .. literalinclude:: note that these are not supported yet, so they will be ignored for now. And any other documentation that the source code would have could go here. -""" - summary_want = summary + "\n" - - summary_got, attributes_got = extension._parse_docstring_summary(summary) - self.assertEqual(summary_got, summary_want) - self.assertEqual(attributes_got, attributes_want) - # Check that exception is raised if code block is not indented. - summary = \ """ + ), + ], + [ + # Tests notices are processed properly. + (\ +""" +.. note:: +\n this is a note. -.. code:: python +.. caution:: +\n another type of notice. -\nprint("This should throw an exception.") -\nfor i in range(10): -\n print(i) -""" - with self.assertRaises(ValueError): - extension._parse_docstring_summary(summary) - # Check that notices are processed properly. - summary_want = \ +.. key-term:: +\n hyphenated term notice. +""" + ), + (\ """""" - - summary = \ + ), + ], + ] + @parameterized.expand(test_entries) + def test_parses_docstring_summary( + self, + summary, + expected_summary, + ): + parsed_summary, attributes = extension._parse_docstring_summary(summary) + self.assertEqual(parsed_summary, expected_summary) + self.assertEqual(attributes, []) + + + test_entries = [ + [ + (\ """ -.. note:: -\n this is a note. -.. caution:: -\n another type of notice. - +.. code:: python -.. key-term:: -\n hyphenated term notice. +\nprint("This should throw an exception.") +\nfor i in range(10): +\n print(i) """ - - summary_got, attributes_got = extension._parse_docstring_summary(summary) - self.assertEqual(summary_got, summary_want) - self.assertEqual(attributes_got, attributes_want) - - # Check that exception is raised if block is not formatted properly. - - summary = \ + ), + ValueError, + ], + [ + (\ """ .. warning:: this is not a properly formatted warning. """ - with self.assertRaises(ValueError): + ), + ValueError, + ], + ] + @parameterized.expand(test_entries) + def test_raises_error_parsing_malformed_docstring( + self, + summary, + error_type + ): + with self.assertRaises(error_type): extension._parse_docstring_summary(summary) - def test_parse_docstring_summary_attributes(self): - # Test parsing docstring with attributes. - attributes_want = [ - { - "id": "simple name", - "description": "simple description", - "var_type": 'str' - } - ] - summary = \ + + test_entries = [ + [ + (\ """ @@ -742,25 +802,16 @@ def test_parse_docstring_summary_attributes(self): \n:type: str """ - - summary_got, attributes_got = extension._parse_docstring_summary(summary) - self.assertCountEqual(attributes_got, attributes_want) - - # Check multiple attributes are parsed. - attributes_want = [ - { + ), + [{ "id": "simple name", "description": "simple description", - "var_type": "str" - }, - { - "id": "table_insert_request", - "description": "Table insert request.", - "var_type": "google.cloud.bigquery_logging_v1.types.TableInsertRequest" - } - ] - - summary = \ + "var_type": "str", + }], + ], + [ + # Tests for multiple attributes. + (\ """ @@ -777,21 +828,21 @@ def test_parse_docstring_summary_attributes(self): \n:type: google.cloud.bigquery_logging_v1.types.TableInsertRequest """ - summary_got, attributes_got = extension._parse_docstring_summary(summary) - - self.assertCountEqual(attributes_got, attributes_want) - for attribute_got, attribute_want in zip(attributes_got, attributes_want): - self.assertDictEqual(attribute_got, attribute_want) - - # Check only attributes in valid format gets parsed. - attributes_want = [ + ), + [{ + "id": "simple name", + "description": "simple description", + "var_type": "str", + }, { - "id": "proper name", - "description": "proper description.", - "var_type": "str" - } - ] - summary = \ + "id": "table_insert_request", + "description": "Table insert request.", + "var_type": "google.cloud.bigquery_logging_v1.types.TableInsertRequest", + }], + ], + [ + # Tests only attributes in valid format are parsed. + (\ """ @@ -808,82 +859,287 @@ def test_parse_docstring_summary_attributes(self): \n:type: str """ - summary_got, attributes_got = extension._parse_docstring_summary(summary) - - # Check that we are returned only one item. - self.assertCountEqual(attributes_got, attributes_want) - for attribute_got, attribute_want in zip(attributes_got, attributes_want): - self.assertDictEqual(attribute_got, attribute_want) - - - def test_merge_markdown_and_package_toc(self): - known_uids = {'acl','batch','blob','client','constants','fileio','hmac_key','notification','retry'} + ), + [{ + "id": "proper name", + "description": "proper description.", + "var_type": "str", + }], + ], + ] + @parameterized.expand(test_entries) + def test_parses_docstring_summary_for_attributes( + self, + summary, + expected_attributes, + ): + _, attributes = extension._parse_docstring_summary(summary) + self.assertCountEqual(attributes, expected_attributes) + for attributes, expected_attributes in zip( + attributes, expected_attributes + ): + self.assertDictEqual(attributes, expected_attributes) + + + def test_merges_markdown_and_package_toc(self): + known_uids = { + "acl", + "batch", + "blob", + "client", + "constants", + "fileio", + "hmac_key", + "notification", + "retry", + } markdown_pages = { - 'storage': [ - {'name': 'FileIO', 'href': 'fileio.md'}, - {'name': 'Retry', 'href': 'retry.md'}, - {'name': 'Notification', 'href': 'notification.md'}, - {'name': 'HMAC Key Metadata', 'href': 'hmac_key.md'}, - {'name': 'Batches', 'href': 'batch.md'}, - {'name': 'Constants', 'href': 'constants.md'}, - {'name': 'Storage Client', 'href': 'client.md'}, - {'name': 'Blobs / Objects', 'href': 'blobs.md'} + "storage": [ + {"name": "FileIO", "href": "fileio.md"}, + {"name": "Retry", "href": "retry.md"}, + {"name": "Notification", "href": "notification.md"}, + {"name": "HMAC Key Metadata", "href": "hmac_key.md"}, + {"name": "Batches", "href": "batch.md"}, + {"name": "Constants", "href": "constants.md"}, + {"name": "Storage Client", "href": "client.md"}, + {"name": "Blobs / Objects", "href": "blobs.md"} ], - 'acl': [ - {'name': 'ACL', 'href': 'acl.md'}, - {'name': 'ACL guide', 'href': 'acl_guide.md'} + "acl": [ + {"name": "ACL", "href": "acl.md"}, + {"name": "ACL guide", "href": "acl_guide.md"} ], - '/': [ - {'name': 'Overview', 'href': 'index.md'}, - {'name': 'Changelog', 'href': 'changelog.md'} + "/": [ + {"name": "Overview", "href": "index.md"}, + {"name": "Changelog", "href": "changelog.md"} ], } pkg_toc_yaml = [ - {'name': 'Storage', - 'items': [ - {'name': 'acl', 'uid': 'google.cloud.storage.acl', 'items': [{'name': 'Overview', 'uid': 'google.cloud.storage.acl'}]}, - {'name': 'batch', 'uid': 'google.cloud.storage.batch', 'items': [{'name': 'Overview', 'uid': 'google.cloud.storage.batch'}]}, - {'name': 'blob', 'uid': 'google.cloud.storage.blob', 'items': [{'name': 'Overview', 'uid': 'google.cloud.storage.blob'}]}, - {'name': 'bucket', 'uid': 'google.cloud.storage.bucket', 'items': [{'name': 'Overview', 'uid': 'google.cloud.storage.bucket'}]}, - {'name': 'client', 'uid': 'google.cloud.storage.client', 'items': [{'name': 'Overview', 'uid': 'google.cloud.storage.client'}]}, - {'name': 'constants', 'uid': 'google.cloud.storage.constants'}, - {'name': 'fileio', 'uid': 'google.cloud.storage.fileio', 'items': [{'name': 'Overview', 'uid': 'google.cloud.storage.fileio'}]}, - {'name': 'hmac_key', 'uid': 'google.cloud.storage.hmac_key', 'items': [{'name': 'Overview', 'uid': 'google.cloud.storage.hmac_key'}]}, - {'name': 'notification', 'uid': 'google.cloud.storage.notification', 'items': [{'name': 'Overview', 'uid': 'google.cloud.storage.notification'}]}, - {'name': 'retry', 'uid': 'google.cloud.storage.retry', 'items': [{'name': 'Overview', 'uid': 'google.cloud.storage.retry'}]}, - ] + {"name": "Storage", + "items": [ + { + "name": "acl", + "uid": "google.cloud.storage.acl", + "items": [ + { + "name": "Overview", + "uid": "google.cloud.storage.acl", + }, + ], + }, + { + "name": "batch", + "uid": "google.cloud.storage.batch", + "items": [ + { + "name": "Overview", + "uid": "google.cloud.storage.batch", + }, + ], + }, + { + "name": "blob", + "uid": "google.cloud.storage.blob", + "items": [ + { + "name": "Overview", + "uid": "google.cloud.storage.blob", + }, + ], + }, + { + "name": "bucket", + "uid": "google.cloud.storage.bucket", + "items": [ + { + "name": "Overview", + "uid": "google.cloud.storage.bucket", + }, + ], + }, + { + "name": "client", + "uid": "google.cloud.storage.client", + "items": [ + { + "name": "Overview", + "uid": "google.cloud.storage.client", + }, + ], + }, + { + "name": "constants", + "uid": "google.cloud.storage.constants", + }, + { + "name": "fileio", + "uid": "google.cloud.storage.fileio", + "items": [ + { + "name": "Overview", + "uid": "google.cloud.storage.fileio", + }, + ], + }, + { + "name": "hmac_key", + "uid": "google.cloud.storage.hmac_key", + "items": [ + { + "name": "Overview", + "uid": "google.cloud.storage.hmac_key", + }, + ], + }, + { + "name": "notification", + "uid": "google.cloud.storage.notification", + "items": [ + { + "name": "Overview", + "uid": "google.cloud.storage.notification"}, + ], + }, + { + "name": "retry", + "uid": "google.cloud.storage.retry", + "items": [ + { + "name": "Overview", + "uid": "google.cloud.storage.retry", + }, + ], + }, + ], }, ] added_pages, merged_pkg_toc_yaml = extension.merge_markdown_and_package_toc( - pkg_toc_yaml, markdown_pages, known_uids) + pkg_toc_yaml, markdown_pages, known_uids + ) - expected_added_pages = {'index.md', 'changelog.md', 'blobs.md', 'acl_guide.md'} expected_merged_pkg_toc_yaml = [ - {'name': 'Overview', 'href': 'index.md'}, - {'name': 'Changelog', 'href': 'changelog.md'}, - {'name': 'Storage', - 'items': [ - {'name': 'Blobs / Objects', 'href': 'blobs.md'}, - {'name': 'acl', 'uid': 'google.cloud.storage.acl', 'items': [ - {'name': 'ACL guide', 'href': 'acl_guide.md'}, - {'name': 'Overview', 'uid': 'google.cloud.storage.acl'}, + {"name": "Overview", "href": "index.md"}, + {"name": "Changelog", "href": "changelog.md"}, + {"name": "Storage", + "items": [ + {"name": "Blobs / Objects", "href": "blobs.md"}, + {"name": "acl", "uid": "google.cloud.storage.acl", "items": [ + {"name": "ACL guide", "href": "acl_guide.md"}, + {"name": "Overview", "uid": "google.cloud.storage.acl"}, ]}, - {'name': 'batch', 'uid': 'google.cloud.storage.batch', 'items': [{'name': 'Overview', 'uid': 'google.cloud.storage.batch'}]}, - {'name': 'blob', 'uid': 'google.cloud.storage.blob', 'items': [{'name': 'Overview', 'uid': 'google.cloud.storage.blob'}]}, - {'name': 'bucket', 'uid': 'google.cloud.storage.bucket', 'items': [{'name': 'Overview', 'uid': 'google.cloud.storage.bucket'}]}, - {'name': 'client', 'uid': 'google.cloud.storage.client', 'items': [{'name': 'Overview', 'uid': 'google.cloud.storage.client'}]}, - {'name': 'constants', 'uid': 'google.cloud.storage.constants'}, - {'name': 'fileio', 'uid': 'google.cloud.storage.fileio', 'items': [{'name': 'Overview', 'uid': 'google.cloud.storage.fileio'}]}, - {'name': 'hmac_key', 'uid': 'google.cloud.storage.hmac_key', 'items': [{'name': 'Overview', 'uid': 'google.cloud.storage.hmac_key'}]}, - {'name': 'notification', 'uid': 'google.cloud.storage.notification', 'items': [{'name': 'Overview', 'uid': 'google.cloud.storage.notification'}]}, - {'name': 'retry', 'uid': 'google.cloud.storage.retry', 'items': [{'name': 'Overview', 'uid': 'google.cloud.storage.retry'}]}, + {"name": "batch", "uid": "google.cloud.storage.batch", "items": [{"name": "Overview", "uid": "google.cloud.storage.batch"}]}, + {"name": "blob", "uid": "google.cloud.storage.blob", "items": [{"name": "Overview", "uid": "google.cloud.storage.blob"}]}, + {"name": "bucket", "uid": "google.cloud.storage.bucket", "items": [{"name": "Overview", "uid": "google.cloud.storage.bucket"}]}, + {"name": "client", "uid": "google.cloud.storage.client", "items": [{"name": "Overview", "uid": "google.cloud.storage.client"}]}, + {"name": "constants", "uid": "google.cloud.storage.constants"}, + {"name": "fileio", "uid": "google.cloud.storage.fileio", "items": [{"name": "Overview", "uid": "google.cloud.storage.fileio"}]}, + {"name": "hmac_key", "uid": "google.cloud.storage.hmac_key", "items": [{"name": "Overview", "uid": "google.cloud.storage.hmac_key"}]}, + {"name": "notification", "uid": "google.cloud.storage.notification", "items": [{"name": "Overview", "uid": "google.cloud.storage.notification"}]}, + {"name": "retry", "uid": "google.cloud.storage.retry", "items": [{"name": "Overview", "uid": "google.cloud.storage.retry"}]}, ] }, ] - self.assertSetEqual(added_pages, expected_added_pages) - self.assertListEqual(merged_pkg_toc_yaml, expected_merged_pkg_toc_yaml) + self.assertSetEqual( + added_pages, + { + "index.md", + "changelog.md", + "blobs.md", + "acl_guide.md", + } + ) + self.assertListEqual( + merged_pkg_toc_yaml, + [ + {"name": "Overview", "href": "index.md"}, + {"name": "Changelog", "href": "changelog.md"}, + {"name": "Storage", + "items": [ + {"name": "Blobs / Objects", "href": "blobs.md"}, + { + "name": "acl", + "uid": "google.cloud.storage.acl", + "items": [ + {"name": "ACL guide", "href": "acl_guide.md"}, + { + "name": "Overview", + "uid": "google.cloud.storage.acl", + }, + ], + }, + { + "name": "batch", + "uid": "google.cloud.storage.batch", + "items": [{ + "name": "Overview", + "uid": "google.cloud.storage.batch", + }], + }, + { + "name": "blob", + "uid": "google.cloud.storage.blob", + "items": [{ + "name": "Overview", + "uid": "google.cloud.storage.blob", + }], + }, + { + "name": "bucket", + "uid": "google.cloud.storage.bucket", + "items": [{ + "name": "Overview", + "uid": "google.cloud.storage.bucket", + }], + }, + { + "name": "client", + "uid": "google.cloud.storage.client", + "items": [{ + "name": "Overview", + "uid": "google.cloud.storage.client", + }], + }, + { + "name": "constants", + "uid": "google.cloud.storage.constants", + }, + { + "name": "fileio", + "uid": "google.cloud.storage.fileio", + "items": [{ + "name": "Overview", + "uid": "google.cloud.storage.fileio", + }], + }, + { + "name": "hmac_key", + "uid": "google.cloud.storage.hmac_key", + "items": [{ + "name": "Overview", + "uid": "google.cloud.storage.hmac_key", + }], + }, + { + "name": "notification", + "uid": "google.cloud.storage.notification", + "items": [{ + "name": "Overview", + "uid": "google.cloud.storage.notification", + }], + }, + { + "name": "retry", + "uid": "google.cloud.storage.retry", + "items": [{ + "name": "Overview", + "uid": "google.cloud.storage.retry", + }], + }, + ], + }, + ], + ), -if __name__ == '__main__': +if __name__ == "__main__": unittest.main()