Skip to content

Commit

Permalink
Changes from comments on PR #2288
Browse files Browse the repository at this point in the history
- 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.
  • Loading branch information
fselmo committed Jan 5, 2022
1 parent 1190d9d commit 971028d
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 49 deletions.
31 changes: 17 additions & 14 deletions docs/web3.main.rst
Expand Up @@ -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:

Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion 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
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
5 changes: 5 additions & 0 deletions tests/core/utilities/test_attach_modules.py
Expand Up @@ -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,
Expand Down
Expand Up @@ -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')
Expand Down
31 changes: 4 additions & 27 deletions web3/main.py
Expand Up @@ -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()
Expand Down

0 comments on commit 971028d

Please sign in to comment.