diff --git a/docs/web3.main.rst b/docs/web3.main.rst index 807e31133a..a05a6fb42d 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,33 @@ 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, { + >>> 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()