From 971028db71def1bcf3653a8fcdb027db2850238a Mon Sep 17 00:00:00 2001 From: Felipe Selmo Date: Wed, 5 Jan 2022 11:54:50 -0700 Subject: [PATCH] Changes from comments on PR #2288 - Add a test to make sure a tuple with a single module class still works for backwards compatibility. - Take out the docstring examples for `attach_modules()` and leave them only in the docs. The consensus is that lengthy docstrings reiterating what is in the documentation would just crowd out our files and make the code harder to read. Instead, we should opt for brief yet useful despritions in the method docstrings. - Change the method to allow for a dict as the argument, as is in the constructor, so that multiple modules may be attached if desired. --- docs/web3.main.rst | 31 ++++++++++--------- newsfragments/2288.feature.rst | 2 +- tests/core/utilities/test_attach_modules.py | 5 +++ ...ttach_module.py => test_attach_modules.py} | 13 ++++---- web3/main.py | 31 +++---------------- 5 files changed, 33 insertions(+), 49 deletions(-) rename tests/core/web3-module/{test_attach_module.py => test_attach_modules.py} (79%) diff --git a/docs/web3.main.rst b/docs/web3.main.rst index 807e31133a..00f0e1227e 100644 --- a/docs/web3.main.rst +++ b/docs/web3.main.rst @@ -416,7 +416,7 @@ Attaching Modules ~~~~~~~~~~~~~~~~~ Modules that inherit from the ``web3.module.Module`` class may be attached to the ``Web3`` instance either at -instantiation or by making use of the ``attach_module()`` method. +instantiation or by making use of the ``attach_modules()`` method. To instantiate the ``Web3`` instance with external modules: @@ -446,31 +446,34 @@ To instantiate the ``Web3`` instance with external modules: 2 -.. py:method:: w3.attach_module(module_name, module) +.. py:method:: w3.attach_modules(modules) - The ``attach_module()`` method can be used to attach an external module after the ``Web3`` instance has been + The ``attach_modules()`` method can be used to attach external modules after the ``Web3`` instance has been instantiated. + Modules are attached via a `dict` with module names as the keys. The values can either be the module classes + themselves, if there are no submodules, or two item tuples with the module class as the 0th index and a similarly + built `dict` containing the submodule information as the 1st index. This pattern may be repeated as necessary. + + .. note:: Module classes must inherit from the ``web3.module.Module`` class. + .. code-block:: python >>> from web3 import Web3, EthereumTesterProvider >>> w3 = Web3(EthereumTesterProvider()) - # attaching a single module - in this case, one with the attribute `return_zero` - >>> w3.attach_module('module1', ModuleClass1) - >>> w3.module1.return_zero - 0 - - # attaching a module with submodules - >>> w3.attach_module( - ... 'module2', - ... (ModuleClass2, { + # attaching modules with submodules + >>> w3.attach_modules({ + ... 'module1': ModuleClass1, # the module class itself may be passed in as the value for a single module with no submodules + ... 'module2': (ModuleClass2, { # a tuple with module class and corresponding submodule dict may be used for modules with submodules ... 'submodule1': ModuleClass3, - ... 'submodule2': (ModuleClass4, { + ... 'submodule2': (ModuleClass4, { # this pattern may be repeated as necessary ... 'submodule2a': ModuleClass5, ... }) ... }) - ... ) + ... }) + >>> w3.module1.return_zero + 0 >>> w3.module2.submodule1.return_one 1 >>> w3.module2.submodule2.submodule2a.return_two diff --git a/newsfragments/2288.feature.rst b/newsfragments/2288.feature.rst index 52cf4c4bd3..102c5e7575 100644 --- a/newsfragments/2288.feature.rst +++ b/newsfragments/2288.feature.rst @@ -1 +1 @@ -Support for attaching external modules to the ``Web3`` instance when instantiating the ``Web3`` instance, via the ``external_modules`` argument, or via the new ``attach_module()`` method \ No newline at end of file +Support for attaching external modules to the ``Web3`` instance when instantiating the ``Web3`` instance, via the ``external_modules`` argument, or via the new ``attach_modules()`` method \ No newline at end of file diff --git a/tests/core/utilities/test_attach_modules.py b/tests/core/utilities/test_attach_modules.py index 9f0fd3f79c..36cb8a563a 100644 --- a/tests/core/utilities/test_attach_modules.py +++ b/tests/core/utilities/test_attach_modules.py @@ -53,6 +53,11 @@ def test_attach_modules(): assert w3.geth.admin.start_ws() is True +def test_attach_single_module_as_tuple(): + w3 = Web3(EthereumTesterProvider(), modules={'eth': (MockEth,)}) + assert w3.eth.block_number() == 42 + + def test_attach_modules_multiple_levels_deep(): mods = { "eth": MockEth, diff --git a/tests/core/web3-module/test_attach_module.py b/tests/core/web3-module/test_attach_modules.py similarity index 79% rename from tests/core/web3-module/test_attach_module.py rename to tests/core/web3-module/test_attach_modules.py index 3493b80352..1b26c6d820 100644 --- a/tests/core/web3-module/test_attach_module.py +++ b/tests/core/web3-module/test_attach_modules.py @@ -3,16 +3,15 @@ ) -def test_attach_module(web3, module1, module2, module3, module4): - web3.attach_module('module1', module1) - web3.attach_module( - 'module2', - (module2, { +def test_attach_modules(web3, module1, module2, module3, module4): + web3.attach_modules({ + 'module1': module1, + 'module2': (module2, { 'submodule1': (module3, { 'submodule2': module4, - }) + }), }) - ) + }) # assert module1 attached assert hasattr(web3, 'module1') diff --git a/web3/main.py b/web3/main.py index 5e38b2b00d..d848c58331 100644 --- a/web3/main.py +++ b/web3/main.py @@ -331,38 +331,15 @@ def solidityKeccak(cls, abi_types: List[TypeStr], values: List[Any]) -> bytes: ))) return cls.keccak(hexstr=hex_string) - def attach_module( + def attach_modules( self, - module_name: str, - module: Union[Type[Module], Sequence[Any]] + modules: Optional[Dict[str, Union[Type[Module], Sequence[Any]]]] ) -> None: """ - Attach a module to the `Web3` instance. Modules should inherit from the `web3.module.Module` + Attach modules to the `Web3` instance. Modules should inherit from the `web3.module.Module` class. - - Attaching a simple module: - - >>> w3.attach_module('module1', ModuleClass1) - >>> w3.module1.return_zero - 0 - - Attaching a module with submodules: - - >>> w3.attach_module( - ... 'module2', - ... (ModuleClass2, { - ... 'submodule1': ModuleClass3, - ... 'submodule2': (ModuleClass4, { - ... 'submodule2a': ModuleClass5, - ... }) - ... }) - ... ) - >>> w3.module2.submodule1.return_one - 1 - >>> w3.module2.submodule2.submodule2a.return_two - 2 """ - attach_modules(self, {module_name: module}) + attach_modules(self, modules) def isConnected(self) -> bool: return self.provider.isConnected()