From 4aeda856288331b677df0423741fdd1bea1e74d4 Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Mon, 9 Sep 2024 11:40:00 -0500 Subject: [PATCH 01/65] Add a hint/note to SSHException when bastion probe fails --- fabrictestbed_extensions/fablib/fablib.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/fabrictestbed_extensions/fablib/fablib.py b/fabrictestbed_extensions/fablib/fablib.py index da8b8595..6f82a977 100644 --- a/fabrictestbed_extensions/fablib/fablib.py +++ b/fabrictestbed_extensions/fablib/fablib.py @@ -68,6 +68,7 @@ import logging import os import random +import sys import traceback import warnings @@ -1696,6 +1697,22 @@ def probe_bastion_host(self) -> bool: f"Error connecting to bastion host {bastion_host} " f"(hint: check your bastion key setup?): {e}" ) + + # Since Python 3.11, we have BaseException.add_note(), + # which is a nicer way of adding some extra information to + # the exception. + # + # https://docs.python.org/3.11/whatsnew/3.11.html#pep-678-exceptions-can-be-enriched-with-notes + # + # With Python versions prior to that, we just append a + # hint to BaseException.args tuple. + if sys.version_info.minor >= 11: + e.add_note("Hint: check your bastion key. Is it valid? Is it expired?") + else: + e.args = e.args + ( + "Hint: check your bastion key. Is it valid? Is it expired?", + ) + raise e except Exception as e: logging.error(f"Error connecting to bastion host {bastion_host}: {e}") From a1072379eda617a8d128ef151f9961ec108bd80d Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Mon, 9 Sep 2024 11:43:21 -0500 Subject: [PATCH 02/65] Add changelog entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c91f1e4c..64474ea9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Missing docstrings in network_service module (Issue [#313](https://github.com/fabric-testbed/fabrictestbed-extensions/issues/314)) - Artifact Manager Support (Issue [#358](https://github.com/fabric-testbed/fabrictestbed-extensions/issues/358)) - FabNet user specified subnets (Issue [#361](https://github.com/fabric-testbed/fabrictestbed-extensions/issues/361)) +- Print a hint when bastion probe fails (Issue [#363](https://github.com/fabric-testbed/fabrictestbed-extensions/issues/363)) ## [1.7.3] - 08/05/2024 ### Fixed From bd00bcec4ba74c656bac80d0529272f43ddf4b9a Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Mon, 9 Sep 2024 13:10:49 -0500 Subject: [PATCH 03/65] Use the right keyword when passing bastion key bastion_key_filename is old; bastion_key_location is the current one. --- tests/integration/test_bastion_ssh.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/integration/test_bastion_ssh.py b/tests/integration/test_bastion_ssh.py index cb42aebd..0a6ba0d7 100644 --- a/tests/integration/test_bastion_ssh.py +++ b/tests/integration/test_bastion_ssh.py @@ -34,7 +34,7 @@ def test_probe_bastion_host_empty_key(self): """ keyfile = tempfile.NamedTemporaryFile() - fm = FablibManager(offline=True, bastion_key_filename=keyfile.name) + fm = FablibManager(offline=True, bastion_key_location=keyfile.name) self.assertRaises(paramiko.ssh_exception.SSHException, fm.probe_bastion_host) def test_probe_bastion_host_bad_key(self): @@ -46,5 +46,5 @@ def test_probe_bastion_host_bad_key(self): rsa_key = paramiko.RSAKey.generate(bits=2048) rsa_key.write_private_key_file(keyfile.name) - fm = FablibManager(offline=True, bastion_key_filename=keyfile.name) + fm = FablibManager(offline=True, bastion_key_location=keyfile.name) self.assertRaises(paramiko.ssh_exception.SSHException, fm.probe_bastion_host) From 42f60f756bfee2e47b726ab2dd7311e2e35c7d95 Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Mon, 9 Sep 2024 13:22:38 -0500 Subject: [PATCH 04/65] Refactor error hint --- fabrictestbed_extensions/fablib/fablib.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/fabrictestbed_extensions/fablib/fablib.py b/fabrictestbed_extensions/fablib/fablib.py index 6f82a977..f7347f89 100644 --- a/fabrictestbed_extensions/fablib/fablib.py +++ b/fabrictestbed_extensions/fablib/fablib.py @@ -1693,9 +1693,9 @@ def probe_bastion_host(self) -> bool: return True except paramiko.SSHException as e: + note = "Hint: check your bastion key. Is it valid? Is it expired?" logging.error( - f"Error connecting to bastion host {bastion_host} " - f"(hint: check your bastion key setup?): {e}" + f"Error connecting to bastion host {bastion_host}: {e} ({note})" ) # Since Python 3.11, we have BaseException.add_note(), @@ -1707,11 +1707,9 @@ def probe_bastion_host(self) -> bool: # With Python versions prior to that, we just append a # hint to BaseException.args tuple. if sys.version_info.minor >= 11: - e.add_note("Hint: check your bastion key. Is it valid? Is it expired?") + e.add_note(note) else: - e.args = e.args + ( - "Hint: check your bastion key. Is it valid? Is it expired?", - ) + e.args = e.args + (note,) raise e except Exception as e: From a391cfc90a71f59cfd5d8ce60a6b7da5f726d251 Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Mon, 9 Sep 2024 13:23:04 -0500 Subject: [PATCH 05/65] Set up logging regardless of offline status --- fabrictestbed_extensions/fablib/fablib.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fabrictestbed_extensions/fablib/fablib.py b/fabrictestbed_extensions/fablib/fablib.py index f7347f89..8de8d49b 100644 --- a/fabrictestbed_extensions/fablib/fablib.py +++ b/fabrictestbed_extensions/fablib/fablib.py @@ -691,9 +691,10 @@ def __init__( self.auto_token_refresh = auto_token_refresh self.last_resources_filtered_by_time = False + self.setup_logging() + if not offline: self.ssh_thread_pool_executor = ThreadPoolExecutor(execute_thread_pool_size) - self.setup_logging() self.__build_manager() self.required_check() From 62656fc34fadbbd64ed1655cf506de90b3dd02b3 Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Mon, 9 Sep 2024 13:24:09 -0500 Subject: [PATCH 06/65] Use correct bastion key path parameter in docstring --- fabrictestbed_extensions/fablib/fablib.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fabrictestbed_extensions/fablib/fablib.py b/fabrictestbed_extensions/fablib/fablib.py index 8de8d49b..c34b8294 100644 --- a/fabrictestbed_extensions/fablib/fablib.py +++ b/fabrictestbed_extensions/fablib/fablib.py @@ -640,7 +640,7 @@ def __init__( https://cm.fabric-testbed.net/, usually via FABRIC portal. :param bastion_username: Your username on FABRIC bastion host, obtained from FABRIC portal. - :param bastion_key_filename: Path to your bastion SSH key. + :param bastion_key_location: Path to your bastion SSH key. :param log_file: Path where fablib logs are written; defaults to ``"/tmp/fablib/fablib.log"``. :param log_level: Level of detail in the logs written. From cf80f08d8e4c4d0ddeb078faf685b97f00527b4b Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Mon, 9 Sep 2024 14:40:22 -0500 Subject: [PATCH 07/65] Assert that we've set bastion parameters correctly Since FablibManager() has a **kwargs, we can't be always sure that the parameters we pass to it are the parameters we meant to pass to it. --- tests/integration/test_bastion_ssh.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/integration/test_bastion_ssh.py b/tests/integration/test_bastion_ssh.py index 0a6ba0d7..e90c289c 100644 --- a/tests/integration/test_bastion_ssh.py +++ b/tests/integration/test_bastion_ssh.py @@ -26,6 +26,7 @@ def test_probe_bastion_host_no_username(self): Test bastion with an empty username. """ fm = FablibManager(offline=True, bastion_username="") + self.assertEqual(fm.get_bastion_username(), "") self.assertRaises(paramiko.ssh_exception.SSHException, fm.probe_bastion_host) def test_probe_bastion_host_empty_key(self): @@ -35,6 +36,7 @@ def test_probe_bastion_host_empty_key(self): keyfile = tempfile.NamedTemporaryFile() fm = FablibManager(offline=True, bastion_key_location=keyfile.name) + self.assertEqual(fm.get_bastion_key_location(), keyfile.name) self.assertRaises(paramiko.ssh_exception.SSHException, fm.probe_bastion_host) def test_probe_bastion_host_bad_key(self): @@ -47,4 +49,5 @@ def test_probe_bastion_host_bad_key(self): rsa_key.write_private_key_file(keyfile.name) fm = FablibManager(offline=True, bastion_key_location=keyfile.name) + self.assertEqual(fm.get_bastion_key_location(), keyfile.name) self.assertRaises(paramiko.ssh_exception.SSHException, fm.probe_bastion_host) From 811d6146f88508163bf3f36a6f03526adcc0a499 Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Mon, 16 Sep 2024 09:56:52 -0500 Subject: [PATCH 08/65] Add missing class docstrings in resources module --- docs/source/resources.rst | 5 ++++- fabrictestbed_extensions/fablib/resources.py | 11 +++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/docs/source/resources.rst b/docs/source/resources.rst index c0ddc9e6..c478687e 100644 --- a/docs/source/resources.rst +++ b/docs/source/resources.rst @@ -6,12 +6,15 @@ resources .. autoclass:: fabrictestbed_extensions.fablib.resources.Resources :members: + :no-index: :special-members: __str__ .. autoclass:: fabrictestbed_extensions.fablib.resources.Links :members: + :no-index: :special-members: __str__ .. autoclass:: fabrictestbed_extensions.fablib.resources.FacilityPorts :members: - :special-members: __str__ \ No newline at end of file + :no-index: + :special-members: __str__ diff --git a/fabrictestbed_extensions/fablib/resources.py b/fabrictestbed_extensions/fablib/resources.py index 96201d85..afcbe6c7 100644 --- a/fabrictestbed_extensions/fablib/resources.py +++ b/fabrictestbed_extensions/fablib/resources.py @@ -45,6 +45,9 @@ class Resources: + """ + A class for working with FABRIC resources. + """ def __init__( self, fablib_manager, @@ -832,6 +835,10 @@ def validate_requested_ero_path(self, source: str, end: str, hops: List[str]): class Links(Resources): + """ + A class for working with network links. + """ + link_pretty_names = { "site_names": "Sites", "node_id": "Link Name", @@ -933,6 +940,10 @@ def list_links( class FacilityPorts(Resources): + """ + A class for working with FABRIC facility ports. + """ + link_pretty_names = { "name": "Name", "site_name": "Site", From 24c426c9739667878bdee9a6662a026439276fd6 Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Mon, 16 Sep 2024 10:05:11 -0500 Subject: [PATCH 09/65] Trim whitespace --- docs/source/network_service.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/network_service.rst b/docs/source/network_service.rst index c9b8fc49..631a50dc 100644 --- a/docs/source/network_service.rst +++ b/docs/source/network_service.rst @@ -6,5 +6,5 @@ network_service .. autoclass:: fabrictestbed_extensions.fablib.network_service.NetworkService :members: - :no-index: + :no-index: :special-members: __str__ From bfe72e2f74637ad26acf106cf55b0343133a2bca Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Mon, 16 Sep 2024 10:05:53 -0500 Subject: [PATCH 10/65] Address warnings when building docs These are the warnings: > fabrictestbed_extensions/fablib/fablib.py:docstring of > fabrictestbed_extensions.fablib.fablib.FablibManager.get_slice_manager:8:Field > list ends without a blank line; unexpected unindent. [docutils] and: > fabrictestbed_extensions/fablib/fablib.py:docstring of > fabrictestbed_extensions.fablib.fablib.FablibManager.set_slice_manager:7:Field > list ends without a blank line; unexpected unindent. [docutils] --- fabrictestbed_extensions/fablib/fablib.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/fabrictestbed_extensions/fablib/fablib.py b/fabrictestbed_extensions/fablib/fablib.py index c34b8294..c32310ff 100644 --- a/fabrictestbed_extensions/fablib/fablib.py +++ b/fabrictestbed_extensions/fablib/fablib.py @@ -1728,7 +1728,9 @@ def set_slice_manager(self, slice_manager: FabricManager): :param slice_manager: the slice manager to set :type slice_manager: SliceManager - .. deprecated:: 1.7.3 Use `set_manager()` instead. + + .. deprecated:: 1.7.3 + Use `set_manager()` instead. """ self.set_manager(manager=slice_manager) @@ -1736,13 +1738,14 @@ def get_slice_manager(self) -> FabricManager: """ Not intended as API call - Gets the slice manager of this fablib object. :return: the slice manager on this fablib object :rtype: SliceManager - .. deprecated:: 1.7.3 Use `get_manager()` instead. - """ + + .. deprecated:: 1.7.3 + Use `get_manager()` instead. + """ return self.get_manager() def set_manager(self, manager: FabricManager): From a40cfaaf610e7eeed2c6fe449986fa20b08085ba Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Mon, 16 Sep 2024 10:08:14 -0500 Subject: [PATCH 11/65] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 64474ea9..0db7e1f4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Artifact Manager Support (Issue [#358](https://github.com/fabric-testbed/fabrictestbed-extensions/issues/358)) - FabNet user specified subnets (Issue [#361](https://github.com/fabric-testbed/fabrictestbed-extensions/issues/361)) - Print a hint when bastion probe fails (Issue [#363](https://github.com/fabric-testbed/fabrictestbed-extensions/issues/363)) +- Missing docstrings in resources module (Issue [#313](https://github.com/fabric-testbed/fabrictestbed-extensions/issues/315)) ## [1.7.3] - 08/05/2024 ### Fixed From 120be0350837b6a1e2f491cc87fd8d27096f3526 Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Mon, 16 Sep 2024 10:20:32 -0500 Subject: [PATCH 12/65] Reformat --- fabrictestbed_extensions/fablib/fablib.py | 2 +- fabrictestbed_extensions/fablib/resources.py | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/fabrictestbed_extensions/fablib/fablib.py b/fabrictestbed_extensions/fablib/fablib.py index c32310ff..0a0c74aa 100644 --- a/fabrictestbed_extensions/fablib/fablib.py +++ b/fabrictestbed_extensions/fablib/fablib.py @@ -1745,7 +1745,7 @@ def get_slice_manager(self) -> FabricManager: .. deprecated:: 1.7.3 Use `get_manager()` instead. - """ + """ return self.get_manager() def set_manager(self, manager: FabricManager): diff --git a/fabrictestbed_extensions/fablib/resources.py b/fabrictestbed_extensions/fablib/resources.py index afcbe6c7..88305f02 100644 --- a/fabrictestbed_extensions/fablib/resources.py +++ b/fabrictestbed_extensions/fablib/resources.py @@ -48,6 +48,7 @@ class Resources: """ A class for working with FABRIC resources. """ + def __init__( self, fablib_manager, @@ -838,7 +839,7 @@ class Links(Resources): """ A class for working with network links. """ - + link_pretty_names = { "site_names": "Sites", "node_id": "Link Name", @@ -943,7 +944,7 @@ class FacilityPorts(Resources): """ A class for working with FABRIC facility ports. """ - + link_pretty_names = { "name": "Name", "site_name": "Site", From 5c7d7a2f5da6c9f6f7831d5a5f0d5c9bfeaa944b Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Mon, 16 Sep 2024 10:15:32 -0500 Subject: [PATCH 13/65] Add docstring to Slice.isReady() --- fabrictestbed_extensions/fablib/slice.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/fabrictestbed_extensions/fablib/slice.py b/fabrictestbed_extensions/fablib/slice.py index 38229b36..a1d5eaa7 100644 --- a/fabrictestbed_extensions/fablib/slice.py +++ b/fabrictestbed_extensions/fablib/slice.py @@ -1913,7 +1913,11 @@ def validIPAddress(self, IP: str) -> str: except ValueError: return "Invalid" - def isReady(self, update=False): + def isReady(self, update=False) -> bool: + """ + Returns `True` if the slice is ready; else returns `False`. + """ + if not self.isStable(): logging.debug( f"isReady: {self.get_name()} not stable ({self.get_state()}), returning false" From 0793a9221430128f4237b588b38b61171c59f4ed Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Mon, 16 Sep 2024 10:19:05 -0500 Subject: [PATCH 14/65] Add docstrings to Slice.get_sliver() and Slice.get_slivers() --- fabrictestbed_extensions/fablib/slice.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/fabrictestbed_extensions/fablib/slice.py b/fabrictestbed_extensions/fablib/slice.py index a1d5eaa7..13af705e 100644 --- a/fabrictestbed_extensions/fablib/slice.py +++ b/fabrictestbed_extensions/fablib/slice.py @@ -671,11 +671,17 @@ def update_slivers(self): raise Exception(f"{slivers}") def get_sliver(self, reservation_id: str) -> OrchestratorSliver: + """ + Returns the sliver associated with the reservation ID. + """ slivers = self.get_slivers() sliver = list(filter(lambda x: x.sliver_id == reservation_id, slivers))[0] return sliver def get_slivers(self) -> List[OrchestratorSliver]: + """ + Returns slivers associated with the slice. + """ if not self.slivers: logging.debug(f"get_slivers", stack_info=False) self.update_slivers() @@ -1917,7 +1923,7 @@ def isReady(self, update=False) -> bool: """ Returns `True` if the slice is ready; else returns `False`. """ - + if not self.isStable(): logging.debug( f"isReady: {self.get_name()} not stable ({self.get_state()}), returning false" From 65c93f057a8f1794743754a41e8eaac91fecfc9f Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Mon, 16 Sep 2024 10:22:24 -0500 Subject: [PATCH 15/65] Add docstring to Slice.get_user_data() --- fabrictestbed_extensions/fablib/slice.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fabrictestbed_extensions/fablib/slice.py b/fabrictestbed_extensions/fablib/slice.py index 13af705e..03cde3bc 100644 --- a/fabrictestbed_extensions/fablib/slice.py +++ b/fabrictestbed_extensions/fablib/slice.py @@ -2815,6 +2815,9 @@ def modify_accept(self): self.update_slice() def get_user_data(self): + """ + Retrieve user data associated with the slice. + """ user_data = {} for node in self.get_nodes(): user_data[node.get_name()] = node.get_user_data() From a1ba66b82982ae5bfba881a9be31908b0f041166 Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Mon, 16 Sep 2024 11:46:43 -0500 Subject: [PATCH 16/65] Correct issue number in PR #366 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0db7e1f4..a3ca3deb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,7 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Artifact Manager Support (Issue [#358](https://github.com/fabric-testbed/fabrictestbed-extensions/issues/358)) - FabNet user specified subnets (Issue [#361](https://github.com/fabric-testbed/fabrictestbed-extensions/issues/361)) - Print a hint when bastion probe fails (Issue [#363](https://github.com/fabric-testbed/fabrictestbed-extensions/issues/363)) -- Missing docstrings in resources module (Issue [#313](https://github.com/fabric-testbed/fabrictestbed-extensions/issues/315)) +- Missing docstrings in resources module (Issue [#315](https://github.com/fabric-testbed/fabrictestbed-extensions/issues/315)) ## [1.7.3] - 08/05/2024 ### Fixed From ef63aa433c1f9e2eed616169b54ec48abe491d36 Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Mon, 16 Sep 2024 11:48:06 -0500 Subject: [PATCH 17/65] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a3ca3deb..ee2e0797 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - FabNet user specified subnets (Issue [#361](https://github.com/fabric-testbed/fabrictestbed-extensions/issues/361)) - Print a hint when bastion probe fails (Issue [#363](https://github.com/fabric-testbed/fabrictestbed-extensions/issues/363)) - Missing docstrings in resources module (Issue [#315](https://github.com/fabric-testbed/fabrictestbed-extensions/issues/315)) +- Missing docstrings in slice module (Issue [#316](https://github.com/fabric-testbed/fabrictestbed-extensions/issues/316)) ## [1.7.3] - 08/05/2024 ### Fixed From 067ca36f8d5aa3153d30518bb8db1035d1778d72 Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Mon, 16 Sep 2024 11:51:43 -0500 Subject: [PATCH 18/65] Add docstring to Component.get_short_name() --- fabrictestbed_extensions/fablib/component.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fabrictestbed_extensions/fablib/component.py b/fabrictestbed_extensions/fablib/component.py index c9eea51b..874932f1 100644 --- a/fabrictestbed_extensions/fablib/component.py +++ b/fabrictestbed_extensions/fablib/component.py @@ -384,6 +384,9 @@ def get_site(self) -> str: return self.node.get_site() def get_short_name(self): + """ + Gets the short name of the component. + """ # strip of the extra parts of the name added by fim return self.get_name()[len(f"{self.get_node().get_name()}-") :] From 2492d5138fea7c3c5b172b14e7d0d60725e92c18 Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Mon, 16 Sep 2024 11:52:29 -0500 Subject: [PATCH 19/65] Add docstring to Component.get_fablib_manager() --- fabrictestbed_extensions/fablib/component.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fabrictestbed_extensions/fablib/component.py b/fabrictestbed_extensions/fablib/component.py index 874932f1..26659ad4 100644 --- a/fabrictestbed_extensions/fablib/component.py +++ b/fabrictestbed_extensions/fablib/component.py @@ -97,6 +97,9 @@ def __str__(self): return tabulate(table) def get_fablib_manager(self): + """ + Get the Fabric library manager associated with the component. + """ return self.get_slice().get_fablib_manager() def toJson(self): From 6058e7b8903b15781056d04aae8722b203d1c29f Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Mon, 16 Sep 2024 11:53:10 -0500 Subject: [PATCH 20/65] Add docstring to Component.get_pretty_name_dict() --- fabrictestbed_extensions/fablib/component.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fabrictestbed_extensions/fablib/component.py b/fabrictestbed_extensions/fablib/component.py index 26659ad4..4055cba1 100644 --- a/fabrictestbed_extensions/fablib/component.py +++ b/fabrictestbed_extensions/fablib/component.py @@ -113,6 +113,9 @@ def toJson(self): @staticmethod def get_pretty_name_dict(): + """ + Returns the mapping used when rendering table headers. + """ return { "name": "Name", "short_name": "Short Name", From 42c863d817737bb31a6b869d0586ae97c2c187d0 Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Mon, 16 Sep 2024 11:55:16 -0500 Subject: [PATCH 21/65] Add docstring to Component.get_fim() --- fabrictestbed_extensions/fablib/component.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/fabrictestbed_extensions/fablib/component.py b/fabrictestbed_extensions/fablib/component.py index 4055cba1..d5c3c4fc 100644 --- a/fabrictestbed_extensions/fablib/component.py +++ b/fabrictestbed_extensions/fablib/component.py @@ -645,6 +645,12 @@ def new_storage(node: Node, name: str, auto_mount: bool = False): return Component(node=node, fim_component=fim_component) def get_fim(self): + """ + Gets the component's FABRIC Information Model (fim) object. + + This method is used to access data at a lower level than + FABlib. + """ return self.get_fim_component() def set_user_data(self, user_data: dict): From 6dd03db834d9ee1564aeadcf7856584a591c6954 Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Mon, 16 Sep 2024 12:07:59 -0500 Subject: [PATCH 22/65] Add docstrings to Component.{set,get}_user_data() --- fabrictestbed_extensions/fablib/component.py | 21 +++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/fabrictestbed_extensions/fablib/component.py b/fabrictestbed_extensions/fablib/component.py index d5c3c4fc..fc3591c7 100644 --- a/fabrictestbed_extensions/fablib/component.py +++ b/fabrictestbed_extensions/fablib/component.py @@ -654,11 +654,30 @@ def get_fim(self): return self.get_fim_component() def set_user_data(self, user_data: dict): + """ + Set the user data for the component. + + This method stores the given user data dictionary as a JSON + string in the FIM object associated with the component. + + :param user_data: The user data to be set. + :type user_data: dict + """ self.get_fim().set_property( pname="user_data", pval=UserData(json.dumps(user_data)) ) - def get_user_data(self): + def get_user_data(self) -> dict: + """ + Retrieve the user data for the component. + + This method fetches the user data stored in the FIM object + associated with the component and returns it as a dictionary. + If an error occurs, it returns an empty dictionary. + + :return: The user data dictionary. + :rtype: dict + """ try: return json.loads(str(self.get_fim().get_property(pname="user_data"))) except: From d88fe207ae1a7b30d0a27be2dd4b25ad414a277a Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Mon, 16 Sep 2024 12:10:32 -0500 Subject: [PATCH 23/65] Add docstring to Component.delete() --- fabrictestbed_extensions/fablib/component.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fabrictestbed_extensions/fablib/component.py b/fabrictestbed_extensions/fablib/component.py index fc3591c7..f4faf0d1 100644 --- a/fabrictestbed_extensions/fablib/component.py +++ b/fabrictestbed_extensions/fablib/component.py @@ -684,6 +684,9 @@ def get_user_data(self) -> dict: return {} def delete(self): + """ + Remove the component from the slice/node. + """ if self.get_interfaces(): for interface in self.get_interfaces(): interface.delete() From 7700d15c626ea0c5046a550031a6a0c0797506c9 Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Mon, 16 Sep 2024 12:11:43 -0500 Subject: [PATCH 24/65] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ee2e0797..3c556597 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Print a hint when bastion probe fails (Issue [#363](https://github.com/fabric-testbed/fabrictestbed-extensions/issues/363)) - Missing docstrings in resources module (Issue [#315](https://github.com/fabric-testbed/fabrictestbed-extensions/issues/315)) - Missing docstrings in slice module (Issue [#316](https://github.com/fabric-testbed/fabrictestbed-extensions/issues/316)) +- Missing docstrings in component module (Issue [#317](https://github.com/fabric-testbed/fabrictestbed-extensions/issues/317)) ## [1.7.3] - 08/05/2024 ### Fixed From 27734dc82a13d69d40652823d2ff38c0270ce895 Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Mon, 16 Sep 2024 12:20:31 -0500 Subject: [PATCH 25/65] Add a docstring to Component class --- docs/source/component.rst | 1 + fabrictestbed_extensions/fablib/component.py | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/docs/source/component.rst b/docs/source/component.rst index 7321e038..1b772078 100644 --- a/docs/source/component.rst +++ b/docs/source/component.rst @@ -6,4 +6,5 @@ component .. autoclass:: fabrictestbed_extensions.fablib.component.Component :members: + :no-index: :special-members: __str__ diff --git a/fabrictestbed_extensions/fablib/component.py b/fabrictestbed_extensions/fablib/component.py index f4faf0d1..575dd890 100644 --- a/fabrictestbed_extensions/fablib/component.py +++ b/fabrictestbed_extensions/fablib/component.py @@ -61,6 +61,10 @@ class Component: + """ + A class for working with FABRIC components. + """ + component_model_map = { Constants.CMP_NIC_Basic: ComponentModelType.SharedNIC_ConnectX_6, Constants.CMP_NIC_ConnectX_6: ComponentModelType.SmartNIC_ConnectX_6, From 78c7e96eb0ef1bce1f7fc037b8479850b6bc4075 Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Mon, 16 Sep 2024 12:23:31 -0500 Subject: [PATCH 26/65] Fix a warning when running `sphinx-build -W` This is the warning: > fabrictestbed_extensions/fablib/slice.py:docstring of > fabrictestbed_extensions.fablib.slice.Slice.add_l3network:53:Field > list ends without a blank line; unexpected unindent. [docutils] --- fabrictestbed_extensions/fablib/slice.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/fabrictestbed_extensions/fablib/slice.py b/fabrictestbed_extensions/fablib/slice.py index 03cde3bc..f59b5ee9 100644 --- a/fabrictestbed_extensions/fablib/slice.py +++ b/fabrictestbed_extensions/fablib/slice.py @@ -1075,15 +1075,17 @@ def add_l3network( :param type: L3 network type "IPv4" or "IPv6" :type type: String - :param user_data + :param user_data: :type user_data: dict - :param technology: Specify the technology used should be set to AL2S when using for AL2S peering; otherwise None + :param technology: Specify the technology used should be set + to AL2S when using for AL2S peering; otherwise None :type technology: str - :param subnet: Request a specific subnet for FabNetv4, FabNetv6 or FabNetv6Ext services. - It's ignored for any other services. - :type ipaddress.ip_network + :param subnet: Request a specific subnet for FabNetv4, + FabNetv6 or FabNetv6Ext services. It's ignored for any + other services. + :type subnet: ipaddress.ip_network :return: a new L3 network service :rtype: NetworkService From 6586eddadd9343b82a12b64861a0833011a4086f Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Mon, 16 Sep 2024 12:31:18 -0500 Subject: [PATCH 27/65] Include artifact and artifact_manager_ui in doc toctree Addressing these warnings: > docs/source/artifact.rst:document isn't included in any toctree and > docs/source/artifact_manager_ui.rst:document isn't included in any > toctree --- docs/source/index.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/source/index.rst b/docs/source/index.rst index bfc95a3f..9ace8148 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -136,6 +136,8 @@ FABLib functionality is made available in these modules: facility_port.rst resources.rst site.rst + artifact + artifact_manager_ui Indices and tables From fb0716e773999f1a98e85ad562c5c817e5aadf08 Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Mon, 16 Sep 2024 14:40:52 -0500 Subject: [PATCH 28/65] Use correct titles Addressing this warnings from `sphinx-build -W`: > docstring of > fabrictestbed_extensions.fablib.interface.Interface:1:more than one > target found for cross-reference 'Switch': > fabrictestbed_extensions.fablib.site.Switch, > fabrictestbed_extensions.fablib.switch.Switch [ref.python] --- docs/source/artifact.rst | 4 ++-- docs/source/artifact_manager_ui.rst | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/source/artifact.rst b/docs/source/artifact.rst index 26600970..0c47ca31 100644 --- a/docs/source/artifact.rst +++ b/docs/source/artifact.rst @@ -1,5 +1,5 @@ -switch -====== +artifact +======== .. automodule:: fabrictestbed_extensions.fablib.artifact :members: diff --git a/docs/source/artifact_manager_ui.rst b/docs/source/artifact_manager_ui.rst index d46d9689..1b0a75a5 100644 --- a/docs/source/artifact_manager_ui.rst +++ b/docs/source/artifact_manager_ui.rst @@ -1,5 +1,5 @@ -switch -====== +artifact_manager_ui +=================== .. automodule:: fabrictestbed_extensions.ui.artifact_manager_ui :members: From 65edec5dc611dab98f0e948e9d6570bdee99d0a7 Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Mon, 16 Sep 2024 14:41:08 -0500 Subject: [PATCH 29/65] Be consistent in toctree --- docs/source/index.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/source/index.rst b/docs/source/index.rst index 9ace8148..298bd2d8 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -131,11 +131,11 @@ FABLib functionality is made available in these modules: node component interface - switch.rst + switch network_service - facility_port.rst - resources.rst - site.rst + facility_port + resources + site artifact artifact_manager_ui From 8a46aa0268fb2a13ba9579aa6cf9f4c81949a18b Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Mon, 16 Sep 2024 16:46:31 -0500 Subject: [PATCH 30/65] Add docstring to fablib.show_config() --- fabrictestbed_extensions/fablib/fablib.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fabrictestbed_extensions/fablib/fablib.py b/fabrictestbed_extensions/fablib/fablib.py index 0a0c74aa..9e4ee4e7 100644 --- a/fabrictestbed_extensions/fablib/fablib.py +++ b/fabrictestbed_extensions/fablib/fablib.py @@ -275,6 +275,9 @@ def get_default_slice_key() -> Dict[str, str]: @staticmethod def show_config(): + """ + Show current FABlib configuration parameters. + """ return fablib.get_default_fablib_manager().show_config() @staticmethod From b6081b9d4e164a2da7dc8e7e04c002afdf05e3f1 Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Mon, 16 Sep 2024 16:48:15 -0500 Subject: [PATCH 31/65] Add a docstring to FablibManager class --- docs/source/fablib.rst | 1 + fabrictestbed_extensions/fablib/fablib.py | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/docs/source/fablib.rst b/docs/source/fablib.rst index e623d27d..40ca1fba 100644 --- a/docs/source/fablib.rst +++ b/docs/source/fablib.rst @@ -6,4 +6,5 @@ fablib .. autoclass:: fabrictestbed_extensions.fablib.fablib.FablibManager :members: + :no-index: :special-members: __str__ diff --git a/fabrictestbed_extensions/fablib/fablib.py b/fabrictestbed_extensions/fablib/fablib.py index 9e4ee4e7..513f04e4 100644 --- a/fabrictestbed_extensions/fablib/fablib.py +++ b/fabrictestbed_extensions/fablib/fablib.py @@ -586,6 +586,10 @@ def is_jupyter_notebook() -> bool: class FablibManager(Config): + """ + The main class to use when interacting with the testbed. + """ + FABNETV4_SUBNET = IPv4Network("10.128.0.0/10") FABNETV6_SUBNET = IPv6Network("2602:FCFB:00::/40") From 1d65896cbc563ed7c4b0bbf1889a56a3be911227 Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Mon, 16 Sep 2024 17:06:26 -0500 Subject: [PATCH 32/65] Add docstring to fablib.is_jupyter_notebook() --- fabrictestbed_extensions/fablib/fablib.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fabrictestbed_extensions/fablib/fablib.py b/fabrictestbed_extensions/fablib/fablib.py index 513f04e4..c9727dbd 100644 --- a/fabrictestbed_extensions/fablib/fablib.py +++ b/fabrictestbed_extensions/fablib/fablib.py @@ -582,6 +582,9 @@ def set_log_level(log_level: str): @staticmethod def is_jupyter_notebook() -> bool: + """ + Check if we're running inside a Jupyter notebook. + """ return fablib.get_default_fablib_manager().is_jupyter_notebook() From 73fd5f7f8278c9873fa53c2e240106c4fb5eac17 Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Mon, 16 Sep 2024 17:06:59 -0500 Subject: [PATCH 33/65] Add docstring to FablibManager.get_ssh_thread_pool_executor() --- fabrictestbed_extensions/fablib/fablib.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fabrictestbed_extensions/fablib/fablib.py b/fabrictestbed_extensions/fablib/fablib.py index c9727dbd..cc0ce713 100644 --- a/fabrictestbed_extensions/fablib/fablib.py +++ b/fabrictestbed_extensions/fablib/fablib.py @@ -1050,6 +1050,9 @@ def __create_and_save_key( os.chmod(public_file_path, 0o644) def get_ssh_thread_pool_executor(self) -> ThreadPoolExecutor: + """ + Get :py:class:`ThreadPoolExecutor` that runs SSH commands. + """ return self.ssh_thread_pool_executor def __build_manager(self) -> FabricManager: From 7b5d79c71c7b80ee2e7f62c648b4afed42b2a370 Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Mon, 16 Sep 2024 17:41:06 -0500 Subject: [PATCH 34/65] Add docstring to FablibManager.show_table_text() --- fabrictestbed_extensions/fablib/fablib.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/fabrictestbed_extensions/fablib/fablib.py b/fabrictestbed_extensions/fablib/fablib.py index cc0ce713..a9149e2a 100644 --- a/fabrictestbed_extensions/fablib/fablib.py +++ b/fabrictestbed_extensions/fablib/fablib.py @@ -2180,6 +2180,19 @@ def is_jupyter_notebook() -> bool: @staticmethod def show_table_text(table, quiet=False): + """ + Make a table in text form suitable for terminal. + + You normally will not use this method directly; you should + rather use :py:meth:`show_table()`. + + :param table: A list of lists. + :param quiet: Setting this to `False` causes the table to be + printed. + + :return: A table formatted by tabulate library. + :rtype: str + """ printable_table = tabulate(table) if not quiet: From 4d2a8b35ad0f0a97ff392186676c5d36059992e9 Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Mon, 16 Sep 2024 17:41:31 -0500 Subject: [PATCH 35/65] Add docstring to FablibManager.show_table_jupyter() --- fabrictestbed_extensions/fablib/fablib.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/fabrictestbed_extensions/fablib/fablib.py b/fabrictestbed_extensions/fablib/fablib.py index a9149e2a..5c2d7df6 100644 --- a/fabrictestbed_extensions/fablib/fablib.py +++ b/fabrictestbed_extensions/fablib/fablib.py @@ -2204,6 +2204,21 @@ def show_table_text(table, quiet=False): def show_table_jupyter( table, headers=None, title="", title_font_size="1.25em", quiet=False ): + """ + Make a table in text form suitable for Jupyter notebooks. + + You normally will not use this method directly; you should + rather use :py:meth:`show_table()`. + + :param table: A list of lists. + :param title: The table title. + :param title_font_size: Font size to use for the table title. + :param quiet: Setting this to `False` causes the table to be + displayed. + + :return: a Pandas dataframe. + :rtype: pd.DataFrame + """ printable_table = pd.DataFrame(table) properties = { From bbcf46d59a0ded0ab4630b6faec356e8c63fce6f Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Mon, 16 Sep 2024 17:41:56 -0500 Subject: [PATCH 36/65] Add docstring to FablibManager.show_table_json() --- fabrictestbed_extensions/fablib/fablib.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/fabrictestbed_extensions/fablib/fablib.py b/fabrictestbed_extensions/fablib/fablib.py index 5c2d7df6..d2565481 100644 --- a/fabrictestbed_extensions/fablib/fablib.py +++ b/fabrictestbed_extensions/fablib/fablib.py @@ -2272,6 +2272,19 @@ def show_table_jupyter( @staticmethod def show_table_json(data, quiet=False): + """ + Make a table in JSON format. + + You normally will not use this method directly; you should + rather use :py:meth:`show_table()`. + + :param data: A list of lists. + :param quiet: Setting this to `False` causes the JSON string + to be printed. + + :return: Table in JSON format. + :rtype: str + """ json_str = json.dumps(data, indent=4) if not quiet: From e9d316a7e0c34bca837bde77334944590ed8d3f3 Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Mon, 16 Sep 2024 17:42:19 -0500 Subject: [PATCH 37/65] Add docstring to FablibManager.show_table_dict() --- fabrictestbed_extensions/fablib/fablib.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/fabrictestbed_extensions/fablib/fablib.py b/fabrictestbed_extensions/fablib/fablib.py index d2565481..368167a8 100644 --- a/fabrictestbed_extensions/fablib/fablib.py +++ b/fabrictestbed_extensions/fablib/fablib.py @@ -2294,6 +2294,20 @@ def show_table_json(data, quiet=False): @staticmethod def show_table_dict(data, quiet=False): + """ + Show the table. + + You normally will not use this method directly; you should + rather use :py:meth:`show_table()`. + + :param data: The table as a Python object; likely a list of + lists. + :param quiet: Setting this to `False` causes the table to be + printed. + + :return: The table as a Python object. + :rtype: str + """ if not quiet: print(f"{data}") From 800202f04249b7620bfbaa15cb7d02329f15f29a Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Mon, 16 Sep 2024 17:52:29 -0500 Subject: [PATCH 38/65] Add docstring to FablibManager.show_table() --- fabrictestbed_extensions/fablib/fablib.py | 32 +++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/fabrictestbed_extensions/fablib/fablib.py b/fabrictestbed_extensions/fablib/fablib.py index 368167a8..d321c5aa 100644 --- a/fabrictestbed_extensions/fablib/fablib.py +++ b/fabrictestbed_extensions/fablib/fablib.py @@ -2323,6 +2323,38 @@ def show_table( quiet=False, pretty_names_dict={}, ): + """ + Format and optionally display a table. + + :param data: The table data, probably a list of lists. + :type data: + + :param fields: Table headers, as a list of strings. + :type fields: + + :param title: Table title. + :type title: str + + :param title_font_size: Font size to use in table title, when + displaying the table in a Jupyter notebook. + :type title_font_size: str + + :param output: The table format. Options are: "text" (or + "default"), or "json", or "dict", or "pandas" (or + "jupyter_default"). + :type output: str + + :param quiet: Display the table, in addition to returning a + table in the required `output` format. + :type quiet: bool + + :param pretty_names_dict: A mapping of non-pretty names to + pretty names to use in table headers. + :type pretty_names_dict: dict + + :return: Depends on `output` parameter. + :rtype: Depends on `output` parameter. + """ if output is None: output = self.output.lower() From f12bb4d549e135135f6052f6e64ef7768e0882cd Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Mon, 16 Sep 2024 17:54:43 -0500 Subject: [PATCH 39/65] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c556597..0deafe35 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Missing docstrings in resources module (Issue [#315](https://github.com/fabric-testbed/fabrictestbed-extensions/issues/315)) - Missing docstrings in slice module (Issue [#316](https://github.com/fabric-testbed/fabrictestbed-extensions/issues/316)) - Missing docstrings in component module (Issue [#317](https://github.com/fabric-testbed/fabrictestbed-extensions/issues/317)) +- Missing docstrings in fablib module (Issue [#319](https://github.com/fabric-testbed/fabrictestbed-extensions/issues/319)) ## [1.7.3] - 08/05/2024 ### Fixed From bb7180a3382cae5ab72d5c32f24d7c406493595f Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Tue, 17 Sep 2024 09:42:13 -0500 Subject: [PATCH 40/65] Add type hints to FablibManager.show_table() --- fabrictestbed_extensions/fablib/fablib.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/fabrictestbed_extensions/fablib/fablib.py b/fabrictestbed_extensions/fablib/fablib.py index d321c5aa..7e031055 100644 --- a/fabrictestbed_extensions/fablib/fablib.py +++ b/fabrictestbed_extensions/fablib/fablib.py @@ -82,7 +82,7 @@ from concurrent.futures import ThreadPoolExecutor from ipaddress import IPv4Network, IPv6Network -from typing import TYPE_CHECKING, Dict, List, Tuple +from typing import TYPE_CHECKING, Any, Dict, List, Tuple import pandas as pd import paramiko @@ -2315,22 +2315,22 @@ def show_table_dict(data, quiet=False): def show_table( self, - data, - fields=None, - title="", - title_font_size="1.25em", - output=None, - quiet=False, - pretty_names_dict={}, + data: List[List[Any]], + fields: List[str] = None, + title: str = "", + title_font_size: str = "1.25em", + output: str = None, + quiet: bool = False, + pretty_names_dict: Dict[str, str] = {}, ): """ Format and optionally display a table. - :param data: The table data, probably a list of lists. - :type data: + :param data: Data to be presented in the table. + :type data: List[List] :param fields: Table headers, as a list of strings. - :type fields: + :type fields: List[str] :param title: Table title. :type title: str From a5b60c31f8b26c775fee0b315f0e20cd04320a3a Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Tue, 17 Sep 2024 09:42:51 -0500 Subject: [PATCH 41/65] Update FablibManager.show_table() docstring --- fabrictestbed_extensions/fablib/fablib.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fabrictestbed_extensions/fablib/fablib.py b/fabrictestbed_extensions/fablib/fablib.py index 7e031055..e894cc37 100644 --- a/fabrictestbed_extensions/fablib/fablib.py +++ b/fabrictestbed_extensions/fablib/fablib.py @@ -2348,11 +2348,11 @@ def show_table( table in the required `output` format. :type quiet: bool - :param pretty_names_dict: A mapping of non-pretty names to + :param pretty_names_dict: A mapping from non-pretty names to pretty names to use in table headers. - :type pretty_names_dict: dict + :type pretty_names_dict: Dict[str,str] - :return: Depends on `output` parameter. + :return: Input :py:obj:`data` formatted as a table. :rtype: Depends on `output` parameter. """ if output is None: From 017c7b44968d1047b423f65b3d61949ec06671af Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Tue, 17 Sep 2024 10:47:44 -0500 Subject: [PATCH 42/65] Use sphinx-autodoc-typehints extension --- docs/source/conf.py | 1 + pyproject.toml | 3 ++- tox.ini | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index cab430ef..5c552043 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -32,6 +32,7 @@ "sphinx.ext.duration", "sphinx.ext.doctest", "sphinx.ext.autodoc", + "sphinx_autodoc_typehints", ] # Add any paths that contain templates here, relative to this directory. diff --git a/pyproject.toml b/pyproject.toml index c7280211..94ac3f8a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -46,7 +46,8 @@ ChangeLog = "https://github.com/fabric-testbed/fabrictestbed-extensions/blob/mai [project.optional-dependencies] doc = [ "sphinx", - "furo" + "sphinx-autodoc-typehints", + "furo", ] test = [ "black==24.*", diff --git a/tox.ini b/tox.ini index 6ee822d9..3c17b0cc 100644 --- a/tox.ini +++ b/tox.ini @@ -24,6 +24,7 @@ commands = # An environment for generanting docs. deps = sphinx + sphinx-autodoc-typehints furo commands = From 83c78aa16c304af9c11a52ebc6b2c39cc105e240 Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Tue, 17 Sep 2024 10:51:27 -0500 Subject: [PATCH 43/65] Add Sphinx viewcode extension --- docs/source/conf.py | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/source/conf.py b/docs/source/conf.py index 5c552043..4547de11 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -33,6 +33,7 @@ "sphinx.ext.doctest", "sphinx.ext.autodoc", "sphinx_autodoc_typehints", + "sphinx.ext.viewcode", ] # Add any paths that contain templates here, relative to this directory. From 00c35df38511f49667f91c723d451837d3a7f07a Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Tue, 17 Sep 2024 10:56:57 -0500 Subject: [PATCH 44/65] Add Sphinx intersphinx extension --- docs/source/conf.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/source/conf.py b/docs/source/conf.py index 4547de11..f5761842 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -34,6 +34,7 @@ "sphinx.ext.autodoc", "sphinx_autodoc_typehints", "sphinx.ext.viewcode", + "sphinx.ext.intersphinx", ] # Add any paths that contain templates here, relative to this directory. @@ -48,6 +49,11 @@ # "class" and "both". autoclass_content = "init" +# Link to Python stdlib docs when possible. +intersphinx_mapping = { + "python": ("https://docs.python.org/3", None), +} + # -- Options for HTML output ------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for From 77c46248843c911ceafb390676d8b74fc658ee16 Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Tue, 17 Sep 2024 11:01:20 -0500 Subject: [PATCH 45/65] Drop types from FablibManager.show_table() docstring The sphinx-autodoc-typehints extension should take care of these things. --- fabrictestbed_extensions/fablib/fablib.py | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/fabrictestbed_extensions/fablib/fablib.py b/fabrictestbed_extensions/fablib/fablib.py index e894cc37..7b03af66 100644 --- a/fabrictestbed_extensions/fablib/fablib.py +++ b/fabrictestbed_extensions/fablib/fablib.py @@ -2327,33 +2327,26 @@ def show_table( Format and optionally display a table. :param data: Data to be presented in the table. - :type data: List[List] :param fields: Table headers, as a list of strings. - :type fields: List[str] :param title: Table title. - :type title: str :param title_font_size: Font size to use in table title, when displaying the table in a Jupyter notebook. - :type title_font_size: str - :param output: The table format. Options are: "text" (or - "default"), or "json", or "dict", or "pandas" (or - "jupyter_default"). - :type output: str + :param output: The table format. Options are: ``"text"`` (or + ``"default"``), or ``"json"``, or ``"dict"``, or + ``"pandas"`` (or ``"jupyter_default"``). :param quiet: Display the table, in addition to returning a table in the required `output` format. - :type quiet: bool :param pretty_names_dict: A mapping from non-pretty names to pretty names to use in table headers. - :type pretty_names_dict: Dict[str,str] :return: Input :py:obj:`data` formatted as a table. - :rtype: Depends on `output` parameter. + :rtype: Depends on :py:obj:`output` parameter. """ if output is None: output = self.output.lower() From 8cd39b16f4fe9099ce49607a7bc806f87e11b586 Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Tue, 17 Sep 2024 13:06:25 -0500 Subject: [PATCH 46/65] Add docstring to FablibManager.create_show_table() --- fabrictestbed_extensions/fablib/fablib.py | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/fabrictestbed_extensions/fablib/fablib.py b/fabrictestbed_extensions/fablib/fablib.py index 7b03af66..b47ea55a 100644 --- a/fabrictestbed_extensions/fablib/fablib.py +++ b/fabrictestbed_extensions/fablib/fablib.py @@ -82,7 +82,7 @@ from concurrent.futures import ThreadPoolExecutor from ipaddress import IPv4Network, IPv6Network -from typing import TYPE_CHECKING, Any, Dict, List, Tuple +from typing import TYPE_CHECKING, Any, Dict, List, Tuple, Union import pandas as pd import paramiko @@ -2552,7 +2552,24 @@ def create_list_table(data, fields=None): return table @staticmethod - def create_show_table(data, fields=None, pretty_names_dict={}): + def create_show_table( + data: Dict[str, Any], + fields: Union[List[str], None] = None, + pretty_names_dict: dict[str, str] = {}, + ) -> List[[Any, Any]]: + """ + Form a table that we can display. + + You should not have to use this method directly; this is used + by :py:meth:`show_table()`. + + :param data: Input data. + :param fields: List of column field names. + :param pretty_names_dict: Mapping from non-pretty to pretty + names, to be used as column labels. + + :return: A list that can be formatted as a table. + """ table = [] if fields is None: for key, value in data.items(): From 2c083e691a95e5b0721c762ad5f6e1a625111224 Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Tue, 17 Sep 2024 13:40:36 -0500 Subject: [PATCH 47/65] Update type hints on FablibManager.show_table() Following orders from `mypy --python-version 3.9 fablib.py` --- fabrictestbed_extensions/fablib/fablib.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fabrictestbed_extensions/fablib/fablib.py b/fabrictestbed_extensions/fablib/fablib.py index b47ea55a..90cd53b1 100644 --- a/fabrictestbed_extensions/fablib/fablib.py +++ b/fabrictestbed_extensions/fablib/fablib.py @@ -2315,11 +2315,11 @@ def show_table_dict(data, quiet=False): def show_table( self, - data: List[List[Any]], - fields: List[str] = None, + data: Dict[str, Any], + fields: Union[List[str], None] = None, title: str = "", title_font_size: str = "1.25em", - output: str = None, + output: Union[str, None] = None, quiet: bool = False, pretty_names_dict: Dict[str, str] = {}, ): From 4b01cadd09c0617c2c0fd45b51545035aff2d4f6 Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Tue, 17 Sep 2024 13:57:06 -0500 Subject: [PATCH 48/65] Add type hints and docstring to FablibManager.list_table() --- fabrictestbed_extensions/fablib/fablib.py | 35 +++++++++++++++++------ 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/fabrictestbed_extensions/fablib/fablib.py b/fabrictestbed_extensions/fablib/fablib.py index 90cd53b1..02b8a77d 100644 --- a/fabrictestbed_extensions/fablib/fablib.py +++ b/fabrictestbed_extensions/fablib/fablib.py @@ -82,7 +82,7 @@ from concurrent.futures import ThreadPoolExecutor from ipaddress import IPv4Network, IPv6Network -from typing import TYPE_CHECKING, Any, Dict, List, Tuple, Union +from typing import TYPE_CHECKING, Any, Callable, Dict, Iterable, List, Tuple, Union import pandas as pd import paramiko @@ -2485,15 +2485,32 @@ def list_table_list(data, quiet=False): def list_table( self, - data, - fields=None, - title="", - title_font_size="1.25em", - output=None, - quiet=False, - filter_function=None, - pretty_names_dict={}, + data: List[Dict[str, str]], + fields: Union[List[str], None] = None, + title: str = "", + title_font_size: str = "1.25em", + output: Union[str, None] = None, + quiet: bool = False, + filter_function: Union[Callable[[Iterable], bool], None] = None, + pretty_names_dict: Dict[str, str] = {}, ): + """ + Format a list into a table that we can display. + + :param data: Data to be formatted. + :param fields: List of column headings. + :param title: Table title. + :param title_font_size: Font size of the table title. + :param output: Output format, which can be one of ``"text"``, + ``"json"``, ``"list"``, or ``"pandas"``. + :param quiet: Prints the table when ``True``. + :param filter_function: A lambda that can be used to filter + the input data. + :param pretty_names_dict: A mapping from non-pretty names to + pretty names, used in column headings. + + :return: Input :py:obj:`data` formatted as a table. + """ if filter_function: data = list(filter(filter_function, data)) From 2c72cd5853c0642156b167d390d500fc208da376 Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Tue, 17 Sep 2024 14:06:07 -0500 Subject: [PATCH 49/65] Add docstring to FablibManager.create_list_table() --- fabrictestbed_extensions/fablib/fablib.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/fabrictestbed_extensions/fablib/fablib.py b/fabrictestbed_extensions/fablib/fablib.py index 02b8a77d..e591e58e 100644 --- a/fabrictestbed_extensions/fablib/fablib.py +++ b/fabrictestbed_extensions/fablib/fablib.py @@ -2558,7 +2558,20 @@ def list_table( logging.error(f"Unknown output type: {output}") @staticmethod - def create_list_table(data, fields=None): + def create_list_table( + data: List[Dict[str, str]], fields: Union[List[str], None] = None + ): + """ + Format a list as a table. + + This method is used by :py:meth:`list_table()`; you do not + have to use this directly. + + :param data: Data to be formatted. + :param fields: List of column titles. + + :return: Tabular data. + """ table = [] for entry in data: row = [] From 83589251c97f701f0eb44877bd0b7bf5aca97d00 Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Tue, 17 Sep 2024 14:10:19 -0500 Subject: [PATCH 50/65] Use correct type hint in create_show_table() return value --- fabrictestbed_extensions/fablib/fablib.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fabrictestbed_extensions/fablib/fablib.py b/fabrictestbed_extensions/fablib/fablib.py index e591e58e..98eaca2f 100644 --- a/fabrictestbed_extensions/fablib/fablib.py +++ b/fabrictestbed_extensions/fablib/fablib.py @@ -2586,7 +2586,7 @@ def create_show_table( data: Dict[str, Any], fields: Union[List[str], None] = None, pretty_names_dict: dict[str, str] = {}, - ) -> List[[Any, Any]]: + ) -> List[List[str]]: """ Form a table that we can display. From 6a707d76540d593206245c803c8519784be888a8 Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Tue, 17 Sep 2024 14:30:48 -0500 Subject: [PATCH 51/65] Add docstrings and type hints to FablibManager.list_table_text() --- fabrictestbed_extensions/fablib/fablib.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/fabrictestbed_extensions/fablib/fablib.py b/fabrictestbed_extensions/fablib/fablib.py index 98eaca2f..9b8d26ea 100644 --- a/fabrictestbed_extensions/fablib/fablib.py +++ b/fabrictestbed_extensions/fablib/fablib.py @@ -2373,7 +2373,23 @@ def show_table( logging.error(f"Unknown output type: {output}") @staticmethod - def list_table_text(table, headers=None, quiet=False): + def list_table_text( + table: List[List[Any]], + headers: Union[List[str], None] = None, + quiet: bool = False, + ): + """ + Format a table as text. + + This is a helper method called by :py:meth:`list_table()`; you + should use that method instead of invoking this directly. + + :param table: A list that :py:func:`tabulate()` can use. + :param headers: List of column headers. + :param quiet: Print the table when ``False``. + + :return: A table-formatted string. + """ if headers is not None: printable_table = tabulate(table, headers=headers) else: From 92ae8555a2e026a858b31bc0dda4d9c87cef0430 Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Tue, 17 Sep 2024 14:38:12 -0500 Subject: [PATCH 52/65] Add type hints and docstring to FablibManager.list_table_jupyter() --- fabrictestbed_extensions/fablib/fablib.py | 24 ++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/fabrictestbed_extensions/fablib/fablib.py b/fabrictestbed_extensions/fablib/fablib.py index 9b8d26ea..f7e9bfc8 100644 --- a/fabrictestbed_extensions/fablib/fablib.py +++ b/fabrictestbed_extensions/fablib/fablib.py @@ -2402,13 +2402,27 @@ def list_table_text( @staticmethod def list_table_jupyter( - table, - headers=None, - title="", - title_font_size="1.25em", + table: List[List[Any]], + headers: Union[List[str], None] = None, + title: str = "", + title_font_size: str = "1.25em", output=None, - quiet=False, + quiet: bool = False, ): + """ + Format a table as a Pandas DataFrame. + + This is a helper method called by :py:meth:`list_table()`; you + should use that method instead of invoking this directly. + + :param table: A list that :py:func:`tabulate()` can use. + :param headers: List of column headers. + :param title: Table title, set as caption for the DataFrame. + :param output: Unused. + :param quiet: Display the table when ``False``. + + :return: A Pandas DataFrame. + """ if len(table) == 0: return None From a81329136c12dae2a8ff3b9cadb72372867db30f Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Tue, 17 Sep 2024 14:49:02 -0500 Subject: [PATCH 53/65] Add docstring to FablibManager.list_table_json() --- fabrictestbed_extensions/fablib/fablib.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/fabrictestbed_extensions/fablib/fablib.py b/fabrictestbed_extensions/fablib/fablib.py index f7e9bfc8..b57fef58 100644 --- a/fabrictestbed_extensions/fablib/fablib.py +++ b/fabrictestbed_extensions/fablib/fablib.py @@ -2498,7 +2498,18 @@ def list_table_jupyter( return printable_table @staticmethod - def list_table_json(data, quiet=False): + def list_table_json(data: List[Dict[str, str]], quiet: bool = False): + """ + Return a JSON representation of table data. + + This is a helper method called by :py:meth:`list_table()`; you + should use that method instead of invoking this directly. + + :param data: Data to be formatted as JSON. + :param quiet: Prints the JSON string when ``False``. + + :return: Some JSON. + """ json_str = json.dumps(data, indent=4) if not quiet: From 0e8c49293588e4c30f310543fb4ae8c887ce7e77 Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Tue, 17 Sep 2024 15:29:39 -0500 Subject: [PATCH 54/65] Add docstring to FablibManager.list_table_list() --- fabrictestbed_extensions/fablib/fablib.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/fabrictestbed_extensions/fablib/fablib.py b/fabrictestbed_extensions/fablib/fablib.py index b57fef58..92823808 100644 --- a/fabrictestbed_extensions/fablib/fablib.py +++ b/fabrictestbed_extensions/fablib/fablib.py @@ -2500,7 +2500,7 @@ def list_table_jupyter( @staticmethod def list_table_json(data: List[Dict[str, str]], quiet: bool = False): """ - Return a JSON representation of table data. + Return a JSON representation of tabular data. This is a helper method called by :py:meth:`list_table()`; you should use that method instead of invoking this directly. @@ -2518,7 +2518,18 @@ def list_table_json(data: List[Dict[str, str]], quiet: bool = False): return json_str @staticmethod - def list_table_list(data, quiet=False): + def list_table_list(data: List[Dict[str, str]], quiet: bool = False): + """ + Return text representation of tabular data. + + This is a helper method called by :py:meth:`list_table()`; you + should use that method instead of invoking this directly. + + :param data: Data to be formatted. + :param quiet: Prints the string when ``False``. + + :return: A table-formatted string. + """ if not quiet: print(f"{data}") From 9148549ae6e1fe13c8ccfabcc311b4f38ebccc7f Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Tue, 17 Sep 2024 15:32:43 -0500 Subject: [PATCH 55/65] Add docstring to fablib.get_default_fablib_manager() --- fabrictestbed_extensions/fablib/fablib.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fabrictestbed_extensions/fablib/fablib.py b/fabrictestbed_extensions/fablib/fablib.py index 92823808..0b019d13 100644 --- a/fabrictestbed_extensions/fablib/fablib.py +++ b/fabrictestbed_extensions/fablib/fablib.py @@ -114,6 +114,9 @@ class fablib: @staticmethod def get_default_fablib_manager(): + """ + Get or create an internal :py:class:`FablibManager` instance. + """ if fablib.default_fablib_manager is None: fablib.default_fablib_manager = FablibManager() From 738e4614df3bad0969856ee8dbee91b78c5a85fc Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Tue, 17 Sep 2024 15:35:31 -0500 Subject: [PATCH 56/65] Add docstring to get_random_sites.combined_filter_function() --- fabrictestbed_extensions/fablib/fablib.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/fabrictestbed_extensions/fablib/fablib.py b/fabrictestbed_extensions/fablib/fablib.py index 0b019d13..bcf3852b 100644 --- a/fabrictestbed_extensions/fablib/fablib.py +++ b/fabrictestbed_extensions/fablib/fablib.py @@ -1623,8 +1623,13 @@ def get_random_sites( :rtype: List[Sting] """ - # Always filter out sites in maintenance and sites that can't support any VMs def combined_filter_function(site): + """ + Filter out "impossible" sites. + + Always filter out sites in maintenance and sites that + can't support any VMs. + """ if filter_function is None: if site["state"] == "Active" and site["hosts"] > 0: return True From cad92e17c0b6d37390468cf055a568aaab1b6bb7 Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Tue, 17 Sep 2024 16:12:15 -0500 Subject: [PATCH 57/65] Add docstrings to fablib.config module --- fabrictestbed_extensions/fablib/config/config.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/fabrictestbed_extensions/fablib/config/config.py b/fabrictestbed_extensions/fablib/config/config.py index de007647..277eacf6 100644 --- a/fabrictestbed_extensions/fablib/config/config.py +++ b/fabrictestbed_extensions/fablib/config/config.py @@ -38,10 +38,18 @@ class ConfigException(Exception): + """ + An exception class to represent configuration errors. + """ + pass class Config: + """ + A class that represents fablib configuration. + """ + LOG_LEVELS = { "DEBUG": logging.DEBUG, "INFO": logging.INFO, @@ -744,6 +752,9 @@ def get_config_pretty_names_dict(self) -> Dict[str, str]: return self.REQUIRED_ATTRS_PRETTY_NAMES def save_config(self): + """ + Write the configuration file. + """ if self.config_file_path is None: print("Config file path not set!") return From 3ba33d52e8dfb3db4a0bf81d3b3e7a1d043c7a40 Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Tue, 17 Sep 2024 16:12:40 -0500 Subject: [PATCH 58/65] Add an interrogate configuration https://interrogate.readthedocs.io/ helps to check the project's docstring coverage. --- pyproject.toml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 94ac3f8a..bc8b89f8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -72,3 +72,16 @@ addopts = "-ra -q" # tests will require some manual setup (namely token acquisition), and # thus we can't run them on CI. testpaths = ["tests/unit/"] + +[tool.interrogate] +ignore-init-method = true +ignore-init-module = true +ignore-magic = true +ignore-module = true +ignore-nested-functions = true +ignore-nested-classes = true +ignore-private = true +ignore-semiprivate = true +omit-covered-files = true +verbose = 0 +exclude = ["tests"] From 15e4e029d2d139b4912627a76c42968bc39899ba Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Tue, 17 Sep 2024 16:25:27 -0500 Subject: [PATCH 59/65] Exclude the old editors module from docstring coverage check --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index bc8b89f8..85562d73 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -84,4 +84,4 @@ ignore-private = true ignore-semiprivate = true omit-covered-files = true verbose = 0 -exclude = ["tests"] +exclude = ["tests", "fabrictestbed_extensions/editors"] From 6a99ac1cc842da8371370c50c7319269558d6d28 Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Tue, 17 Sep 2024 16:27:45 -0500 Subject: [PATCH 60/65] Add a GitHub Actions workflow to check docstring coverage --- .github/workflows/docstrings.yml | 34 ++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 .github/workflows/docstrings.yml diff --git a/.github/workflows/docstrings.yml b/.github/workflows/docstrings.yml new file mode 100644 index 00000000..3ca3a9f5 --- /dev/null +++ b/.github/workflows/docstrings.yml @@ -0,0 +1,34 @@ +name: Check docstring coverage + +on: + push: + branches: + - "main" + pull_request: + workflow_dispatch: + +permissions: + contents: read + +jobs: + + checks: + runs-on: ubuntu-latest + + steps: + - name: Check out sources + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.x" + cache: 'pip' # cache pip dependencies + cache-dependency-path: pyproject.toml + + # See https://github.com/JackMcKew/python-interrogate-check + - name: Check docstring coverage with interrogate + uses: JackMcKew/python-interrogate-check@v0.1.2 + with: + path: "fabrictestbed_extensions" + fail-under: "92" From a24c491c695a374a819e011ade796841f725a630 Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Tue, 17 Sep 2024 16:31:38 -0500 Subject: [PATCH 61/65] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0deafe35..bb05380a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Missing docstrings in slice module (Issue [#316](https://github.com/fabric-testbed/fabrictestbed-extensions/issues/316)) - Missing docstrings in component module (Issue [#317](https://github.com/fabric-testbed/fabrictestbed-extensions/issues/317)) - Missing docstrings in fablib module (Issue [#319](https://github.com/fabric-testbed/fabrictestbed-extensions/issues/319)) +- Missing docstrings in fablib.config module (Issue [#320](https://github.com/fabric-testbed/fabrictestbed-extensions/issues/320)) ## [1.7.3] - 08/05/2024 ### Fixed From a7a538e41e3769de09036d2432f77ea60be2b63a Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Tue, 17 Sep 2024 17:13:05 -0500 Subject: [PATCH 62/65] Fail interrogate when docstring coverage falls under current status --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index 85562d73..42381760 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -84,4 +84,5 @@ ignore-private = true ignore-semiprivate = true omit-covered-files = true verbose = 0 +fail-under = 92.6 exclude = ["tests", "fabrictestbed_extensions/editors"] From 5bc178fb385f486dd22f0e940107e30c1e9279a0 Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Tue, 17 Sep 2024 17:18:13 -0500 Subject: [PATCH 63/65] Install and run interrogate with Python The version of interrogate on JackMcKew/python-interrogate-check action is 1.2.0, which is too old. --- .github/workflows/docstrings.yml | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/.github/workflows/docstrings.yml b/.github/workflows/docstrings.yml index 3ca3a9f5..ccf9fa90 100644 --- a/.github/workflows/docstrings.yml +++ b/.github/workflows/docstrings.yml @@ -26,9 +26,11 @@ jobs: cache: 'pip' # cache pip dependencies cache-dependency-path: pyproject.toml - # See https://github.com/JackMcKew/python-interrogate-check + - name: Install interrogate + run: | + python -m pip install --upgrade pip + python -m pip install interrogate==1.7.0 + - name: Check docstring coverage with interrogate - uses: JackMcKew/python-interrogate-check@v0.1.2 - with: - path: "fabrictestbed_extensions" - fail-under: "92" + run: | + python -m interrogate -vv fabrictestbed_extensions From a379448ba14dba8097bfcf116e484ed83ad6dc7b Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Tue, 17 Sep 2024 17:28:27 -0500 Subject: [PATCH 64/65] Rename workflow file --- .../workflows/{docstrings.yml => check_docstring_coverage.yml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .github/workflows/{docstrings.yml => check_docstring_coverage.yml} (100%) diff --git a/.github/workflows/docstrings.yml b/.github/workflows/check_docstring_coverage.yml similarity index 100% rename from .github/workflows/docstrings.yml rename to .github/workflows/check_docstring_coverage.yml From fc2fd6c92612720f47a144218d0ec715593b9b80 Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Tue, 17 Sep 2024 17:33:07 -0500 Subject: [PATCH 65/65] Add some commentary about the workflow --- .github/workflows/check_docstring_coverage.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/check_docstring_coverage.yml b/.github/workflows/check_docstring_coverage.yml index ccf9fa90..11335a6a 100644 --- a/.github/workflows/check_docstring_coverage.yml +++ b/.github/workflows/check_docstring_coverage.yml @@ -1,3 +1,9 @@ +# A check to ensure that our docstring coverage remains pretty good. +# +# We use interrogate (https://interrogate.readthedocs.io/) to check +# docstring coverage. Settings are under `[tool.interrogate]` section +# of the pyproject.toml file in the top-level directory. + name: Check docstring coverage on: