prompt: 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()
  
  ```
  
golden_diff: 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:
  
verification_info: {"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"}]}