We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Web3 instantiation from subclass throws error
* Version: 5.30.0
* Python: 3.8
* OS: osx
* pip freeze output is intentionally omitted.

### What was wrong?
We use a sub-class of Web3, for the purpose of this example, call it SubclassWeb3, as follows:

```
class SubclassWeb3(Web3):
def __init__(self, ....):
  ... do bunch of stuff...
  super().__init__(*args, **kwargs)
  ... do bunch more stuff...
```

This setup worked fine with web3 version == 5.23.1. However, switching to web3==5.30.0 breaks this, with error

```
[rest of callstack omitted]
 File “[redacted]/web3/main.py”, line 251, in __init__
    self.attach_modules(modules)
  File “[redacted]/web3/main.py”, line 340, in attach_modules
    _attach_modules(self, modules)
  File “[redacted]/web3/_utils/module.py”, line 68, in attach_modules
    setattr(parent_module, module_name, module_class(w3))
  File “[redacted]/web3/module.py”, line 93, in __init__
    self.codec: ABICodec = web3.codec
AttributeError: ‘NoneType’ object has no attribute ‘codec’
```

This used to work in older versions because the parent_module is assumed to be a Web3 object and stored accordingly - [see logic](https://github.com/ethereum/web3.py/blob/2b229d2e16792e52bb47108e665c6a8937c188a2/web3/_utils/module.py#L33-L35).

Compare this to the somewhat brittle name checking that happens in 5.30.0 - [see logic](https://github.com/ethereum/web3.py/blob/ee5f0543ad91e4ba991997e35f50719ceb58135d/web3/_utils/module.py#L58-L60). This doesn't quite work because if this logic is being executed from a subclass of Web3, the name of the parent module appears as SubclassWeb3 (and not Web3).

### How can it be fixed?

Fill this section in if you know how this could or should be fixed.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `web3/_utils/module.py`
Content:
```
1 import inspect
2 from io import (
3     UnsupportedOperation,
4 )
5 from typing import (
6     TYPE_CHECKING,
7     Any,
8     Dict,
9     List,
10     Optional,
11     Sequence,
12     Union,
13 )
14 
15 from web3.exceptions import (
16     ValidationError,
17 )
18 from web3.module import (
19     Module,
20 )
21 
22 if TYPE_CHECKING:
23     from web3 import Web3  # noqa: F401
24 
25 
26 def _validate_init_params_and_return_if_found(module_class: Any) -> List[str]:
27     init_params_raw = list(inspect.signature(module_class.__init__).parameters)
28     module_init_params = [
29         param for param in init_params_raw if param not in ['self', 'args', 'kwargs']
30     ]
31 
32     if len(module_init_params) > 1:
33         raise UnsupportedOperation(
34             "A module class may accept a single `Web3` instance as the first argument of its "
35             f"__init__() method. More than one argument found for {module_class.__name__}: "
36             f"{module_init_params}"
37         )
38 
39     return module_init_params
40 
41 
42 def attach_modules(
43     parent_module: Union["Web3", "Module"],
44     module_definitions: Dict[str, Any],
45     w3: Optional[Union["Web3", "Module"]] = None
46 ) -> None:
47     for module_name, module_info in module_definitions.items():
48         module_info_is_list_like = isinstance(module_info, Sequence)
49 
50         module_class = module_info[0] if module_info_is_list_like else module_info
51 
52         if hasattr(parent_module, module_name):
53             raise AttributeError(
54                 f"Cannot set {parent_module} module named '{module_name}'.  The web3 object "
55                 "already has an attribute with that name"
56             )
57 
58         # The parent module is the ``Web3`` instance on first run of the loop
59         if type(parent_module).__name__ == 'Web3':
60             w3 = parent_module
61 
62         module_init_params = _validate_init_params_and_return_if_found(module_class)
63         if len(module_init_params) == 1:
64             # Modules that need access to the ``Web3`` instance may accept the instance as the first
65             # arg in their ``__init__()`` method. This is the case for any module that inherits from
66             # ``web3.module.Module``.
67             # e.g. def __init__(self, w3):
68             setattr(parent_module, module_name, module_class(w3))
69         else:
70             # Modules need not take in a ``Web3`` instance in their ``__init__()`` if not needed
71             setattr(parent_module, module_name, module_class())
72 
73         if module_info_is_list_like:
74             if len(module_info) == 2:
75                 submodule_definitions = module_info[1]
76                 module = getattr(parent_module, module_name)
77                 attach_modules(module, submodule_definitions, w3)
78             elif len(module_info) != 1:
79                 raise ValidationError("Module definitions can only have 1 or 2 elements.")
80
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/web3/_utils/module.py b/web3/_utils/module.py
--- a/web3/_utils/module.py
+++ b/web3/_utils/module.py
@@ -55,9 +55,13 @@
                 "already has an attribute with that name"
             )
 
-        # The parent module is the ``Web3`` instance on first run of the loop
-        if type(parent_module).__name__ == 'Web3':
-            w3 = parent_module
+        # The parent module is the ``Web3`` instance on first run of the loop and w3 is
+        # None. Thus, set w3 to the parent_module. The import needs to happen locally
+        # due to circular import issues.
+        if w3 is None:
+            from web3 import Web3
+            if isinstance(parent_module, Web3):
+                w3 = parent_module
 
         module_init_params = _validate_init_params_and_return_if_found(module_class)
         if len(module_init_params) == 1:

{"golden_diff": "diff --git a/web3/_utils/module.py b/web3/_utils/module.py\n--- a/web3/_utils/module.py\n+++ b/web3/_utils/module.py\n@@ -55,9 +55,13 @@\n                 \"already has an attribute with that name\"\n             )\n \n-        # The parent module is the ``Web3`` instance on first run of the loop\n-        if type(parent_module).__name__ == 'Web3':\n-            w3 = parent_module\n+        # The parent module is the ``Web3`` instance on first run of the loop and w3 is\n+        # None. Thus, set w3 to the parent_module. The import needs to happen locally\n+        # due to circular import issues.\n+        if w3 is None:\n+            from web3 import Web3\n+            if isinstance(parent_module, Web3):\n+                w3 = parent_module\n \n         module_init_params = _validate_init_params_and_return_if_found(module_class)\n         if len(module_init_params) == 1:\n", "issue": "Web3 instantiation from subclass throws error\n* Version: 5.30.0\r\n* Python: 3.8\r\n* OS: osx\r\n* pip freeze output is intentionally omitted.\r\n\r\n### What was wrong?\r\nWe use a sub-class of Web3, for the purpose of this example, call it SubclassWeb3, as follows:\r\n\r\n```\r\nclass SubclassWeb3(Web3):\r\ndef __init__(self, ....):\r\n  ... do bunch of stuff...\r\n  super().__init__(*args, **kwargs)\r\n  ... do bunch more stuff...\r\n```\r\n\r\nThis setup worked fine with web3 version == 5.23.1. However, switching to web3==5.30.0 breaks this, with error\r\n\r\n```\r\n[rest of callstack omitted]\r\n File \u201c[redacted]/web3/main.py\u201d, line 251, in __init__\r\n    self.attach_modules(modules)\r\n  File \u201c[redacted]/web3/main.py\u201d, line 340, in attach_modules\r\n    _attach_modules(self, modules)\r\n  File \u201c[redacted]/web3/_utils/module.py\u201d, line 68, in attach_modules\r\n    setattr(parent_module, module_name, module_class(w3))\r\n  File \u201c[redacted]/web3/module.py\u201d, line 93, in __init__\r\n    self.codec: ABICodec = web3.codec\r\nAttributeError: \u2018NoneType\u2019 object has no attribute \u2018codec\u2019\r\n```\r\n\r\nThis used to work in older versions because the parent_module is assumed to be a Web3 object and stored accordingly - [see logic](https://github.com/ethereum/web3.py/blob/2b229d2e16792e52bb47108e665c6a8937c188a2/web3/_utils/module.py#L33-L35).\r\n\r\nCompare this to the somewhat brittle name checking that happens in 5.30.0 - [see logic](https://github.com/ethereum/web3.py/blob/ee5f0543ad91e4ba991997e35f50719ceb58135d/web3/_utils/module.py#L58-L60). This doesn't quite work because if this logic is being executed from a subclass of Web3, the name of the parent module appears as SubclassWeb3 (and not Web3).\r\n\r\n### How can it be fixed?\r\n\r\nFill this section in if you know how this could or should be fixed.\n", "before_files": [{"content": "import inspect\nfrom io import (\n    UnsupportedOperation,\n)\nfrom typing import (\n    TYPE_CHECKING,\n    Any,\n    Dict,\n    List,\n    Optional,\n    Sequence,\n    Union,\n)\n\nfrom web3.exceptions import (\n    ValidationError,\n)\nfrom web3.module import (\n    Module,\n)\n\nif TYPE_CHECKING:\n    from web3 import Web3  # noqa: F401\n\n\ndef _validate_init_params_and_return_if_found(module_class: Any) -> List[str]:\n    init_params_raw = list(inspect.signature(module_class.__init__).parameters)\n    module_init_params = [\n        param for param in init_params_raw if param not in ['self', 'args', 'kwargs']\n    ]\n\n    if len(module_init_params) > 1:\n        raise UnsupportedOperation(\n            \"A module class may accept a single `Web3` instance as the first argument of its \"\n            f\"__init__() method. More than one argument found for {module_class.__name__}: \"\n            f\"{module_init_params}\"\n        )\n\n    return module_init_params\n\n\ndef attach_modules(\n    parent_module: Union[\"Web3\", \"Module\"],\n    module_definitions: Dict[str, Any],\n    w3: Optional[Union[\"Web3\", \"Module\"]] = None\n) -> None:\n    for module_name, module_info in module_definitions.items():\n        module_info_is_list_like = isinstance(module_info, Sequence)\n\n        module_class = module_info[0] if module_info_is_list_like else module_info\n\n        if hasattr(parent_module, module_name):\n            raise AttributeError(\n                f\"Cannot set {parent_module} module named '{module_name}'.  The web3 object \"\n                \"already has an attribute with that name\"\n            )\n\n        # The parent module is the ``Web3`` instance on first run of the loop\n        if type(parent_module).__name__ == 'Web3':\n            w3 = parent_module\n\n        module_init_params = _validate_init_params_and_return_if_found(module_class)\n        if len(module_init_params) == 1:\n            # Modules that need access to the ``Web3`` instance may accept the instance as the first\n            # arg in their ``__init__()`` method. This is the case for any module that inherits from\n            # ``web3.module.Module``.\n            # e.g. def __init__(self, w3):\n            setattr(parent_module, module_name, module_class(w3))\n        else:\n            # Modules need not take in a ``Web3`` instance in their ``__init__()`` if not needed\n            setattr(parent_module, module_name, module_class())\n\n        if module_info_is_list_like:\n            if len(module_info) == 2:\n                submodule_definitions = module_info[1]\n                module = getattr(parent_module, module_name)\n                attach_modules(module, submodule_definitions, w3)\n            elif len(module_info) != 1:\n                raise ValidationError(\"Module definitions can only have 1 or 2 elements.\")\n", "path": "web3/_utils/module.py"}], "after_files": [{"content": "import inspect\nfrom io import (\n    UnsupportedOperation,\n)\nfrom typing import (\n    TYPE_CHECKING,\n    Any,\n    Dict,\n    List,\n    Optional,\n    Sequence,\n    Union,\n)\n\nfrom web3.exceptions import (\n    ValidationError,\n)\nfrom web3.module import (\n    Module,\n)\n\nif TYPE_CHECKING:\n    from web3 import Web3  # noqa: F401\n\n\ndef _validate_init_params_and_return_if_found(module_class: Any) -> List[str]:\n    init_params_raw = list(inspect.signature(module_class.__init__).parameters)\n    module_init_params = [\n        param for param in init_params_raw if param not in ['self', 'args', 'kwargs']\n    ]\n\n    if len(module_init_params) > 1:\n        raise UnsupportedOperation(\n            \"A module class may accept a single `Web3` instance as the first argument of its \"\n            f\"__init__() method. More than one argument found for {module_class.__name__}: \"\n            f\"{module_init_params}\"\n        )\n\n    return module_init_params\n\n\ndef attach_modules(\n    parent_module: Union[\"Web3\", \"Module\"],\n    module_definitions: Dict[str, Any],\n    w3: Optional[Union[\"Web3\", \"Module\"]] = None\n) -> None:\n    for module_name, module_info in module_definitions.items():\n        module_info_is_list_like = isinstance(module_info, Sequence)\n\n        module_class = module_info[0] if module_info_is_list_like else module_info\n\n        if hasattr(parent_module, module_name):\n            raise AttributeError(\n                f\"Cannot set {parent_module} module named '{module_name}'.  The web3 object \"\n                \"already has an attribute with that name\"\n            )\n\n        # The parent module is the ``Web3`` instance on first run of the loop and w3 is\n        # None. Thus, set w3 to the parent_module. The import needs to happen locally\n        # due to circular import issues.\n        if w3 is None:\n            from web3 import Web3\n            if isinstance(parent_module, Web3):\n                w3 = parent_module\n\n        module_init_params = _validate_init_params_and_return_if_found(module_class)\n        if len(module_init_params) == 1:\n            # Modules that need access to the ``Web3`` instance may accept the instance as the first\n            # arg in their ``__init__()`` method. This is the case for any module that inherits from\n            # ``web3.module.Module``.\n            # e.g. def __init__(self, w3):\n            setattr(parent_module, module_name, module_class(w3))\n        else:\n            # Modules need not take in a ``Web3`` instance in their ``__init__()`` if not needed\n            setattr(parent_module, module_name, module_class())\n\n        if module_info_is_list_like:\n            if len(module_info) == 2:\n                submodule_definitions = module_info[1]\n                module = getattr(parent_module, module_name)\n                attach_modules(module, submodule_definitions, w3)\n            elif len(module_info) != 1:\n                raise ValidationError(\"Module definitions can only have 1 or 2 elements.\")\n", "path": "web3/_utils/module.py"}]}