Repository: ethereum/web3.py (python)

Issue:
gethdev AutoProvider does not consider the WEB3_PROVIDER_URI environment variable
* Version: 5.13.0
* Python: 3.8.5
* OS: Linux (Ubuntu 20.04.1 LTS)

### What was wrong?

When using `web3.auto.gethdev`, the `WEB3_PROVIDER_URI` environment variable does not appear to be honored.

```
$ export WEB3_PROVIDER_URI=file:///path/to/node/geth.ipc

$ python3
Python 3.8.5 (default, Jul 28 2020, 12:59:40)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from web3.auto.gethdev import w3
>>> w3.eth.filter({'fromBlock': 'latest'})

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/<path>/.local/lib/python3.8/site-packages/web3/eth.py", line 491, in filter
    _filter_id = self.web3.manager.request_blocking(
  File "/<path>/.local/lib/python3.8/site-packages/web3/manager.py", line 154, in request_blocking
    response = self._make_request(method, params)
  File "/<path>/.local/lib/python3.8/site-packages/web3/manager.py", line 133, in _make_request
    return request_func(method, params)
  File "cytoolz/functoolz.pyx", line 250, in cytoolz.functoolz.curry.__call__
  File "/<path>/.local/lib/python3.8/site-packages/web3/middleware/formatting.py", line 74, in apply_formatters
    response = make_request(method, formatted_params)
  File "/<path>/.local/lib/python3.8/site-packages/web3/middleware/gas_price_strategy.py", line 34, in middleware
    return make_request(method, params)
  File "cytoolz/functoolz.pyx", line 250, in cytoolz.functoolz.curry.__call__
  File "/<path>/.local/lib/python3.8/site-packages/web3/middleware/formatting.py", line 74, in apply_formatters
    response = make_request(method, formatted_params)
  File "/<path>/.local/lib/python3.8/site-packages/web3/middleware/attrdict.py", line 33, in middleware
    response = make_request(method, params)
  File "cytoolz/functoolz.pyx", line 250, in cytoolz.functoolz.curry.__call__
  File "/<path>/.local/lib/python3.8/site-packages/web3/middleware/formatting.py", line 74, in apply_formatters
    response = make_request(method, formatted_params)
  File "/<path>/.local/lib/python3.8/site-packages/web3/middleware/normalize_errors.py", line 25, in middleware
    result = make_request(method, params)
  File "cytoolz/functoolz.pyx", line 250, in cytoolz.functoolz.curry.__call__
  File "/<path>/.local/lib/python3.8/site-packages/web3/middleware/formatting.py", line 76, in apply_formatters
    response = make_request(method, params)
  File "cytoolz/functoolz.pyx", line 250, in cytoolz.functoolz.curry.__call__
  File "/<path>/.local/lib/python3.8/site-packages/web3/middleware/formatting.py", line 74, in apply_formatters
    response = make_request(method, formatted_params)
  File "cytoolz/functoolz.pyx", line 250, in cytoolz.functoolz.curry.__call__
  File "/<path>/.local/lib/python3.8/site-packages/web3/middleware/formatting.py", line 76, in apply_formatters
    response = make_request(method, params)
  File "/<path>/.local/lib/python3.8/site-packages/web3/providers/ipc.py", line 234, in make_request
    with self._lock, self._socket as sock:
  File "/<path>/.local/lib/python3.8/site-packages/web3/providers/ipc.py", line 55, in __enter__
    raise FileNotFoundError("cannot connect to IPC socket at path: %r" % self.ipc_path)
FileNotFoundError: cannot connect to IPC socket at path: None
```

### How can it be fixed?

Apply this environment variable to the gethdev autoprovider.

Pull request description:
Honor WEB3_PROVIDER_URI for geth auto dev connection
### What was wrong?

Connecting via the gethdev auto provider didn't look first for the `WEB3_PROVIDER_URI` environment variable. 

Fixes #1817 

### How was it fixed?

Added a check at the beginning of the `get_dev_ipc_path` function for the WEB3_PROVIDER_URI environment variable. 

### Todo:
- [x] Add entry to the [release notes](https://github.com/ethereum/web3.py/blob/master/newsfragments/README.md)

#### Cute Animal Picture

![Put a link to a cute animal picture inside the parenthesis-->](https://twistedsifter.com/wp-content/uploads/2012/05/adorable-baby-elephant-1.jpg)


Patch:
diff --git a/docs/internals.rst b/docs/internals.rst
index e5e1deec..faf4afcc 100644
--- a/docs/internals.rst
+++ b/docs/internals.rst
@@ -80,16 +80,6 @@ HTTP or an IPC socket.  There is however nothing which requires providers to be
 RPC based, allowing for providers designed for testing purposes which use an
 in-memory EVM to fulfill requests.
 
-In most simple cases you will be using a single provider.  However, if you
-would like to use Web3 with multiple providers, you can simply pass them in as
-a list when instantiating your ``Web3`` object.
-
-
-.. code-block:: python
-
-    >>> w3 = Web3([provider_a, provider_b])
-
-
 
 Writing your own Provider
 ~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/newsfragments/2018.doc.rst b/newsfragments/2018.doc.rst
new file mode 100644
index 00000000..ffc80739
--- /dev/null
+++ b/newsfragments/2018.doc.rst
@@ -0,0 +1,1 @@
+Remove reference to allowing multiple providers in docs
diff --git a/newsfragments/2023.bugfix.rst b/newsfragments/2023.bugfix.rst
new file mode 100644
index 00000000..7f1d261e
--- /dev/null
+++ b/newsfragments/2023.bugfix.rst
@@ -0,0 +1,1 @@
+Have the geth dev IPC auto connection check for the ``WEB3_PROVIDER_URI`` environment variable.
diff --git a/newsfragments/2025.misc.rst b/newsfragments/2025.misc.rst
new file mode 100644
index 00000000..d48c0df1
--- /dev/null
+++ b/newsfragments/2025.misc.rst
@@ -0,0 +1,1 @@
+Remove redundant async/await in AsyncJSONBaseProvider serde methods
diff --git a/newsfragments/2028.misc.rst b/newsfragments/2028.misc.rst
new file mode 100644
index 00000000..3f4c7970
--- /dev/null
+++ b/newsfragments/2028.misc.rst
@@ -0,0 +1,1 @@
+Update to flaky version >=3.7.0,<4
\ No newline at end of file
diff --git a/setup.py b/setup.py
index 451e751a..90090074 100644
--- a/setup.py
+++ b/setup.py
@@ -34,7 +34,7 @@ extras_require = {
     ],
     'dev': [
         "bumpversion",
-        "flaky>=3.3.0",
+        "flaky>=3.7.0,<4",
         "hypothesis>=3.31.2,<6",
         "pytest>=4.4.0,<5.0.0",
         "pytest-asyncio>=0.10.0,<0.11",
diff --git a/web3/providers/async_base.py b/web3/providers/async_base.py
index 4720357c..1d446389 100644
--- a/web3/providers/async_base.py
+++ b/web3/providers/async_base.py
@@ -85,7 +85,7 @@ class AsyncJSONBaseProvider(AsyncBaseProvider):
     def __init__(self) -> None:
         self.request_counter = itertools.count()
 
-    async def encode_rpc_request(self, method: RPCEndpoint, params: Any) -> bytes:
+    def encode_rpc_request(self, method: RPCEndpoint, params: Any) -> bytes:
         rpc_dict = {
             "jsonrpc": "2.0",
             "method": method,
@@ -95,7 +95,7 @@ class AsyncJSONBaseProvider(AsyncBaseProvider):
         encoded = FriendlyJsonSerde().json_encode(rpc_dict)
         return to_bytes(text=encoded)
 
-    async def decode_rpc_response(self, raw_response: bytes) -> RPCResponse:
+    def decode_rpc_response(self, raw_response: bytes) -> RPCResponse:
         text_response = to_text(raw_response)
         return cast(RPCResponse, FriendlyJsonSerde().json_decode(text_response))
 
diff --git a/web3/providers/async_rpc.py b/web3/providers/async_rpc.py
index 695bd10f..82f945a4 100644
--- a/web3/providers/async_rpc.py
+++ b/web3/providers/async_rpc.py
@@ -69,13 +69,13 @@ class AsyncHTTPProvider(AsyncJSONBaseProvider):
     async def make_request(self, method: RPCEndpoint, params: Any) -> RPCResponse:
         self.logger.debug("Making request HTTP. URI: %s, Method: %s",
                           self.endpoint_uri, method)
-        request_data = await self.encode_rpc_request(method, params)
+        request_data = self.encode_rpc_request(method, params)
         raw_response = await async_make_post_request(
             self.endpoint_uri,
             request_data,
             **self.get_request_kwargs()
         )
-        response = await self.decode_rpc_response(raw_response)
+        response = self.decode_rpc_response(raw_response)
         self.logger.debug("Getting response HTTP. URI: %s, "
                           "Method: %s, Response: %s",
                           self.endpoint_uri, method, response)
diff --git a/web3/providers/ipc.py b/web3/providers/ipc.py
index 57a2998a..45faf63b 100644
--- a/web3/providers/ipc.py
+++ b/web3/providers/ipc.py
@@ -157,7 +157,11 @@ def get_default_ipc_path() -> str:  # type: ignore
 
 # type ignored b/c missing return statement is by design here
 def get_dev_ipc_path() -> str:  # type: ignore
-    if sys.platform == 'darwin':
+    if os.environ.get('WEB3_PROVIDER_URI', ''):
+        ipc_path = os.environ.get('WEB3_PROVIDER_URI')
+        if os.path.exists(ipc_path):
+            return ipc_path
+    elif sys.platform == 'darwin':
         tmpdir = os.environ.get('TMPDIR', '')
         ipc_path = os.path.expanduser(os.path.join(
             tmpdir,


Test patch:
diff --git a/tests/core/providers/test_auto_provider.py b/tests/core/providers/test_auto_provider.py
index 6fd773a9..c0e30295 100644
--- a/tests/core/providers/test_auto_provider.py
+++ b/tests/core/providers/test_auto_provider.py
@@ -17,6 +17,9 @@ from web3.providers import (
 from web3.providers.auto import (
     load_provider_from_environment,
 )
+from web3.providers.ipc import (
+    get_dev_ipc_path,
+)
 
 # Ugly hack to import infura now that API KEY is required
 os.environ['WEB3_INFURA_API_KEY'] = 'test'
@@ -51,6 +54,13 @@ def test_load_provider_from_env(monkeypatch, uri, expected_type, expected_attrs)
         assert getattr(provider, attr) == val
 
 
+def test_get_dev_ipc_path(monkeypatch, tmp_path):
+    uri = str(tmp_path)
+    monkeypatch.setenv('WEB3_PROVIDER_URI', uri)
+    path = get_dev_ipc_path()
+    assert path == uri
+
+
 @pytest.mark.parametrize('environ_name', ['WEB3_INFURA_API_KEY', 'WEB3_INFURA_PROJECT_ID'])
 def test_web3_auto_infura_empty_key(monkeypatch, caplog, environ_name):
     monkeypatch.setenv('WEB3_INFURA_SCHEME', 'https')