Repository: hlf20010508/miniopy-async (language: python)

Issue:
warning msg: Unclosed client session,  Unclosed connector
# Bug Report

## Describe the bug
I got this warning:
```txt
example one
Unclosed client session
client_session: <aiohttp.client.ClientSession object at 0x105883820>
Unclosed connector
connections: ['[(<aiohttp.client_proto.ResponseHandler object at 0x1062769a0>, 0.497560541)]']
connector: <aiohttp.connector.TCPConnector object at 0x10626bfa0>
Unclosed client session
client_session: <aiohttp.client.ClientSession object at 0x10626bfd0>
Unclosed connector
connections: ['[(<aiohttp.client_proto.ResponseHandler object at 0x106276820>, 0.524557333)]']
connector: <aiohttp.connector.TCPConnector object at 0x10628c460>
created my-object object; etag: 5d41402abc4b2a76b9719d911017c592, version-id: 5868d1d6-5085-43b1-bb43-425fded2f2a4
```

## To Reproduce
Steps to reproduce the behavior:
My code is like this:
```python
import io
from miniopy_async import Minio
import asyncio

client = Minio(
        "play.min.io",
        access_key="Q3AM3UQ867SPQQA43P2F",
        secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
    )


async def main():
    # Upload data.
    print('example one')
    result = await client.put_object(
        "test", "my-object", io.BytesIO(b"hello"), 5,
    )
    print(
        "created {0} object; etag: {1}, version-id: {2}".format(
            result.object_name, result.etag, result.version_id,
        ),
    )


if __name__ == "__main__":
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())
    loop.close()
```

## Expected behavior
I think the sesson or connection should be closed automatically, or some close api to use.

## Desktop:
 - OS: macos m1 pro
 - Browser [e.g. chrome, safari]
 - Version 13.0.1





Discussion / hints:
I changed the code to this:
``` python
    async def _url_open(  # pylint: disable=too-many-branches
        self,
        method,
        region,
        bucket_name=None,
        object_name=None,
        body=None,
        headers=None,
        query_params=None,
        session=None,
    ):
        """Execute HTTP request."""
        credentials = self._provider.retrieve() if self._provider else None
        url = self._base_url.build(
            method,
            region,
            bucket_name=bucket_name,
            object_name=object_name,
            query_params=query_params,
        )
        headers, date = await self._build_headers(
            url.netloc,
            headers,
            body,
            credentials
        )
        if credentials:
            headers = sign_v4_s3(
                method,
                url,
                region,
                headers,
                credentials,
                headers.get("x-amz-content-sha256"),
                date,
            )      
        if session is None:
            async with aiohttp.ClientSession() as session:
                return await self._do_req_in_session(session, method, url, body, headers)
        else:
            return await self._do_req_in_session(session, method, url, body, headers)

    async def _do_req_in_session(self, session, method, url, body, headers):
        response = await session.request(
            method,
            urlunsplit(url),
            data=body,
            headers=headers)

        # if should_attach_finalizer:
        #     _attach_finalizer(response, session, asyncio.get_running_loop())

        if response.status in [200, 204, 206]:
            return response

        response_data = await response.content.read()
        content_types = response.headers.get("content-type", "").split(";")
        if method != "HEAD" and "application/xml" not in content_types:
            raise InvalidResponseError(
                response.status,
                response.headers.get("content-type"),
                response_data if response_data else None,
            )

        if not response_data and method != "HEAD":
            raise InvalidResponseError(
                response.status,
                response.headers.get("content-type"),
                None,
            )

        response_error = S3Error.fromxml(
            response, response_data
        ) if response_data else None

        error_map = {
            301: lambda: self._handle_redirect_response(
                method, bucket_name, response, True,
            ),
            307: lambda: self._handle_redirect_response(
                method, bucket_name, response, True,
            ),
            400: lambda: self._handle_redirect_response(
                method, bucket_name, response, True,
            ),
            403: lambda: ("AccessDenied", "Access denied"),
            404: lambda: (
                ("NoSuchKey", "Object does not exist")
                if object_name
                else ("NoSuchBucket", "Bucket does not exist")
                if bucket_name
                else ("ResourceNotFound", "Request resource not found")
            ),
            405: lambda: (
                "MethodNotAllowed",
                "The specified method is not allowed against this resource",
            ),
            409: lambda: (
                ("NoSuchBucket", "Bucket does not exist")
                if bucket_name
                else ("ResourceConflict", "Request resource conflicts"),
            ),
            501: lambda: (
                "MethodNotAllowed",
                "The specified method is not allowed against this resource",
            ),
        }

        if not response_error:
            func = error_map.get(response.status)
            code, message = func() if func else (None, None)
            if not code:
                raise ServerError(
                    f"server failed with HTTP status code {response.status}",
                    response.status
                )
            response_error = S3Error(
                code,
                message,
                url.path,
                response.headers.get("x-amz-request-id"),
                response.headers.get("x-amz-id-2"),
                response,
                bucket_name=bucket_name,
                object_name=object_name,
            )

        if response_error.code in ["NoSuchBucket", "RetryHead"]:
            self._region_map.pop(bucket_name, None)

        raise response_error
```
then, it worked well.
I've tried your modified code.
When using `fget_object`, your code cannot download anything.
`Unclosed connector` is a warning, not critical, but annoy.
However, it's hard to remove this warning while keeping every function workable.

Fix patch:
diff --git a/.gitignore b/.gitignore
index 308e6ae..202efab 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,8 +2,7 @@
 __pycache__/
 *.py[cod]
 .DS_Store
-test.py
-testfile
+testfile*
 
 # C extensions
 *.so
diff --git a/README.md b/README.md
index 2311e37..91bdba8 100644
--- a/README.md
+++ b/README.md
@@ -76,17 +76,19 @@ client = Minio(
     secure=True  # http for False, https for True
 )
 
+
 async def main():
     url = await client.presigned_get_object("my-bucket", "my-object")
     print('url:', url)
 
+
 loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
 loop.close()
 ```
 
 ```py
-from sanic import Sanic
+from sanic import Sanic, response
 from miniopy_async import Minio
 from urllib import parse
 
@@ -99,17 +101,19 @@ client = Minio(
     secure=True  # http for False, https for True
 )
 
+
+# http://127.0.0.1:8000/download?bucket=my-bucket&fileName=testfile
 @app.route('/download', methods=['GET'])
 async def download(request):
     print('downloading ...')
-    bucket=request.form.get('bucket')
-    fileName=request.form.get('fileName')
+    bucket=request.args.get('bucket')
+    fileName=request.args.get('fileName')
 
     # decodeURI, for those which has other language in fileName, such as Chinese, Japanese, Korean
     fileName = parse.unquote(fileName)
 
     url = await client.presigned_get_object(bucket_name=bucket, object_name=fileName)
-    return redirect(url)
+    return response.redirect(url)
 ```
 
 <span id="references"></span>
diff --git a/docs/API.md b/docs/API.md
index 9915c27..e46ef73 100644
--- a/docs/API.md
+++ b/docs/API.md
@@ -899,7 +899,7 @@ __Example__
 
 ```py
 from miniopy_async import Minio
-from miniopy_async.commonconfig import DISABLED, ENABLED, AndOperator, Filter
+from miniopy_async.commonconfig import DISABLED, ENABLED, AndOperator, Filter, Tags
 from miniopy_async.replicationconfig import (DeleteMarkerReplication, Destination, ReplicationConfig, Rule)
 import asyncio
 
@@ -910,6 +910,10 @@ client = Minio(
     secure=True  # http for False, https for True
 )
 
+bucket_tags = Tags.new_bucket_tags()
+bucket_tags["Project"] = "Project One"
+bucket_tags["User"] = "jsmith"
+
 config = ReplicationConfig(
     "REPLACE-WITH-ACTUAL-ROLE",
     [
@@ -924,7 +928,7 @@ config = ReplicationConfig(
             rule_filter=Filter(
                 AndOperator(
                     "TaxDocs",
-                    {"key1": "value1", "key2": "value2"},
+                    bucket_tags,
                 ),
             ),
             rule_id="rule1",
diff --git a/examples/sanic/run.py b/examples/sanic/run.py
index 06ea931..01f8853 100644
--- a/examples/sanic/run.py
+++ b/examples/sanic/run.py
@@ -23,47 +23,58 @@
 from urllib import parse
 
 app = Sanic(__name__)
-template = SanicJinja2(app, pkg_name='run') # pkg_name is the main file name, here is for run.py
+template = SanicJinja2(
+    app, pkg_name="run"
+)  # pkg_name is the main file name, here is for run.py
 
 
 client = Minio(
     "play.min.io",
     access_key="Q3AM3UQ867SPQQA43P2F",
     secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
-    secure=True  # http for False, https for True
+    secure=True,  # http for False, https for True
 )
 
 
-@app.route('/', methods=['POST', 'GET'])
+@app.route("/", methods=["POST", "GET"])
 async def index(request):
-    if request.method == 'POST':
-        f = request.files.get('file')
-        if f:  # if f is not None then the post request is from upload, else is from download
-            print('uploading ...')
-            save_path = os.path.join('cache', f.name)  # save stream to cache
-            async with aiofiles.open(save_path, 'wb') as temp:
+    if request.method == "POST":
+        f = request.files.get("file")
+        if (
+            f
+        ):  # if f is not None then the post request is from upload, else is from download
+            print("uploading ...")
+            save_path = os.path.join("cache", f.name)  # save stream to cache
+            async with aiofiles.open(save_path, "wb") as temp:
                 await temp.write(f.body)
             temp.close()
 
-            bucket = request.form.get('bucket')
+            bucket = request.form.get("bucket")
             # upload from cache
-            await client.fput_object(bucket_name=bucket, object_name=f.name, file_path=save_path)
+            await client.fput_object(
+                bucket_name=bucket, object_name=f.name, file_path=save_path
+            )
             os.remove(save_path)  # clear cache
 
-            return redirect(app.url_for('index'))
+            return redirect(app.url_for("index"))
         else:  # redirect to download
-            bucket = request.form.get('bucket')
-            file_name = request.form.get('fileName')
-            return redirect(app.url_for('download', bucket=bucket, fileName=file_name))
-    return template.render('index.html', request)
+            bucket = request.form.get("bucket")
+            file_name = request.form.get("fileName")
+            return redirect(app.url_for("download", bucket=bucket, fileName=file_name))
+    return template.render("index.html", request)
 
 
-@app.route('/download/<bucket>/<fileName>', methods=['GET'])
+@app.route("/download/<bucket>/<fileName>", methods=["GET"])
 async def download(request, bucket, fileName):
-    print('downloading ...')
-    fileName = parse.unquote(fileName) # decodeURI, for those which has other language in fileName, such as Chinese, Japanese, Korean
-    url = await client.presigned_get_object(bucket_name=bucket, object_name=fileName) # get download url from minio, expiry default to 7 days 
+    print("downloading ...")
+    fileName = parse.unquote(
+        fileName
+    )  # decodeURI, for those which has other language in fileName, such as Chinese, Japanese, Korean
+    url = await client.presigned_get_object(
+        bucket_name=bucket, object_name=fileName
+    )  # get download url from minio, expiry default to 7 days
     return redirect(url)
 
-if __name__ == '__main__':
-    app.run(host='0.0.0.0', port=8080, debug=True)
+
+if __name__ == "__main__":
+    app.run(host="0.0.0.0", port=8080, debug=True)
diff --git a/examples/sanic/templates/index.html b/examples/sanic/templates/index.html
index 15b2bb8..8fb0c26 100644
--- a/examples/sanic/templates/index.html
+++ b/examples/sanic/templates/index.html
@@ -17,11 +17,13 @@
 
 <!DOCTYPE html>
 <html>
+
 <head>
     <meta charset=utf-8>
     <meta name=viewport content="width=device-width,initial-scale=1">
     <title>Example</title>
 </head>
+
 <body>
     <h1>Example</h1>
     <form action="" enctype='multipart/form-data' method='POST'>
@@ -41,4 +43,5 @@ <h1>Example</h1>
         <input type="submit" value="download">
     </form>
 </body>
+
 </html>
\ No newline at end of file
diff --git a/examples/simple_examples/bucket_exists.py b/examples/simple_examples/bucket_exists.py
index 93d4198..1befac1 100644
--- a/examples/simple_examples/bucket_exists.py
+++ b/examples/simple_examples/bucket_exists.py
@@ -26,9 +26,10 @@
     "play.min.io",
     access_key="Q3AM3UQ867SPQQA43P2F",
     secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
-    secure=True  # http for False, https for True
+    secure=True,  # http for False, https for True
 )
 
+
 async def main():
     result = await client.bucket_exists("my-bucket")
     if result:
@@ -36,6 +37,7 @@ async def main():
     else:
         print("my-bucket does not exist")
 
+
 loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
 loop.close()
diff --git a/examples/simple_examples/compose_object.py b/examples/simple_examples/compose_object.py
index 5d95f14..8942b69 100644
--- a/examples/simple_examples/compose_object.py
+++ b/examples/simple_examples/compose_object.py
@@ -28,7 +28,7 @@
     "play.min.io",
     access_key="Q3AM3UQ867SPQQA43P2F",
     secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
-    secure=True  # http for False, https for True
+    secure=True,  # http for False, https for True
 )
 
 # Each part must larger than 5MB
@@ -38,16 +38,17 @@
     ComposeSource("my-job-bucket", "my-object-part-three"),
 ]
 
+
 async def main():
     # Create my-bucket/my-object by combining source object
     # list.
-    print('example one')
+    print("example one")
     result = await client.compose_object("my-bucket", "my-object", sources)
     print(result.object_name, result.version_id)
 
     # Create my-bucket/my-object with user metadata by combining
     # source object list.
-    print('example two')
+    print("example two")
     result = await client.compose_object(
         "my-bucket",
         "my-object",
@@ -58,15 +59,11 @@ async def main():
 
     # Create my-bucket/my-object with user metadata and
     # server-side encryption by combining source object list.
-    print('example three')
-    result = await client.compose_object(
-        "my-bucket",
-        "my-object",
-        sources,
-        sse=SseS3()
-    )
+    print("example three")
+    result = await client.compose_object("my-bucket", "my-object", sources, sse=SseS3())
     print(result.object_name, result.version_id)
 
+
 loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
 loop.close()
diff --git a/examples/simple_examples/copy_object.py b/examples/simple_examples/copy_object.py
index 0b3b1f1..7e3227d 100644
--- a/examples/simple_examples/copy_object.py
+++ b/examples/simple_examples/copy_object.py
@@ -28,9 +28,10 @@
     "play.min.io",
     access_key="Q3AM3UQ867SPQQA43P2F",
     secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
-    secure=True  # http for False, https for True
+    secure=True,  # http for False, https for True
 )
 
+
 async def main():
     # copy an object from a bucket to another.
     print("example one")
@@ -66,6 +67,7 @@ async def main():
     )
     print(result.object_name, result.version_id)
 
+
 loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
 loop.close()
diff --git a/examples/simple_examples/delete_bucket_encryption.py b/examples/simple_examples/delete_bucket_encryption.py
index d1a23c0..c035656 100644
--- a/examples/simple_examples/delete_bucket_encryption.py
+++ b/examples/simple_examples/delete_bucket_encryption.py
@@ -26,12 +26,14 @@
     "play.min.io",
     access_key="Q3AM3UQ867SPQQA43P2F",
     secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
-    secure=True  # http for False, https for True
+    secure=True,  # http for False, https for True
 )
 
+
 async def main():
     await client.delete_bucket_encryption("my-bucket")
 
-loop=asyncio.get_event_loop()
+
+loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
 loop.close()
diff --git a/examples/simple_examples/delete_bucket_lifecycle.py b/examples/simple_examples/delete_bucket_lifecycle.py
index d6d7516..cf94dfb 100644
--- a/examples/simple_examples/delete_bucket_lifecycle.py
+++ b/examples/simple_examples/delete_bucket_lifecycle.py
@@ -26,12 +26,14 @@
     "play.min.io",
     access_key="Q3AM3UQ867SPQQA43P2F",
     secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
-    secure=True  # http for False, https for True
+    secure=True,  # http for False, https for True
 )
 
+
 async def main():
     await client.delete_bucket_lifecycle("my-bucket")
 
+
 loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
 loop.close()
diff --git a/examples/simple_examples/delete_bucket_notification.py b/examples/simple_examples/delete_bucket_notification.py
index e48b222..d316266 100644
--- a/examples/simple_examples/delete_bucket_notification.py
+++ b/examples/simple_examples/delete_bucket_notification.py
@@ -26,12 +26,14 @@
     "play.min.io",
     access_key="Q3AM3UQ867SPQQA43P2F",
     secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
-    secure=True  # http for False, https for True
+    secure=True,  # http for False, https for True
 )
 
+
 async def main():
     await client.delete_bucket_notification("my-bucket")
 
-loop=asyncio.get_event_loop()
+
+loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
 loop.close()
diff --git a/examples/simple_examples/delete_bucket_policy.py b/examples/simple_examples/delete_bucket_policy.py
index 6bf2c47..82c0335 100644
--- a/examples/simple_examples/delete_bucket_policy.py
+++ b/examples/simple_examples/delete_bucket_policy.py
@@ -26,12 +26,14 @@
     "play.min.io",
     access_key="Q3AM3UQ867SPQQA43P2F",
     secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
-    secure=True  # http for False, https for True
+    secure=True,  # http for False, https for True
 )
 
+
 async def main():
     await client.delete_bucket_policy("my-bucket")
 
-loop=asyncio.get_event_loop()
+
+loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
 loop.close()
diff --git a/examples/simple_examples/delete_bucket_replication.py b/examples/simple_examples/delete_bucket_replication.py
index 939af4e..f93230e 100644
--- a/examples/simple_examples/delete_bucket_replication.py
+++ b/examples/simple_examples/delete_bucket_replication.py
@@ -26,12 +26,14 @@
     "play.min.io",
     access_key="Q3AM3UQ867SPQQA43P2F",
     secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
-    secure=True  # http for False, https for True
+    secure=True,  # http for False, https for True
 )
 
+
 async def main():
     await client.delete_bucket_replication("my-bucket")
 
-loop=asyncio.get_event_loop()
+
+loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
 loop.close()
diff --git a/examples/simple_examples/delete_bucket_tags.py b/examples/simple_examples/delete_bucket_tags.py
index 6b6cc54..dda4e8a 100644
--- a/examples/simple_examples/delete_bucket_tags.py
+++ b/examples/simple_examples/delete_bucket_tags.py
@@ -26,12 +26,14 @@
     "play.min.io",
     access_key="Q3AM3UQ867SPQQA43P2F",
     secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
-    secure=True  # http for False, https for True
+    secure=True,  # http for False, https for True
 )
 
+
 async def main():
     await client.delete_bucket_tags("my-bucket")
 
-loop=asyncio.get_event_loop()
+
+loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
 loop.close()
diff --git a/examples/simple_examples/delete_object_lock_config.py b/examples/simple_examples/delete_object_lock_config.py
index fc3edb3..e23273d 100644
--- a/examples/simple_examples/delete_object_lock_config.py
+++ b/examples/simple_examples/delete_object_lock_config.py
@@ -26,12 +26,14 @@
     "play.min.io",
     access_key="Q3AM3UQ867SPQQA43P2F",
     secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
-    secure=True  # http for False, https for True
+    secure=True,  # http for False, https for True
 )
 
+
 async def main():
     await client.delete_object_lock_config("my-bucket")
 
-loop=asyncio.get_event_loop()
+
+loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
 loop.close()
diff --git a/examples/simple_examples/delete_object_tags.py b/examples/simple_examples/delete_object_tags.py
index 28b47c8..8fd51f4 100644
--- a/examples/simple_examples/delete_object_tags.py
+++ b/examples/simple_examples/delete_object_tags.py
@@ -26,12 +26,14 @@
     "play.min.io",
     access_key="Q3AM3UQ867SPQQA43P2F",
     secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
-    secure=True  # http for False, https for True
+    secure=True,  # http for False, https for True
 )
 
+
 async def main():
     await client.delete_object_tags("my-bucket")
 
-loop=asyncio.get_event_loop()
+
+loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
 loop.close()
diff --git a/examples/simple_examples/disable_object_legal_hold.py b/examples/simple_examples/disable_object_legal_hold.py
index d0107df..920a232 100644
--- a/examples/simple_examples/disable_object_legal_hold.py
+++ b/examples/simple_examples/disable_object_legal_hold.py
@@ -26,12 +26,14 @@
     "play.min.io",
     access_key="Q3AM3UQ867SPQQA43P2F",
     secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
-    secure=True  # http for False, https for True
+    secure=True,  # http for False, https for True
 )
 
+
 async def main():
     await client.disable_object_legal_hold("my-bucket", "my-object")
 
-loop=asyncio.get_event_loop()
+
+loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
 loop.close()
diff --git a/examples/simple_examples/enable_object_legal_hold.py b/examples/simple_examples/enable_object_legal_hold.py
index afbdf1f..cfe7f36 100644
--- a/examples/simple_examples/enable_object_legal_hold.py
+++ b/examples/simple_examples/enable_object_legal_hold.py
@@ -26,12 +26,14 @@
     "play.min.io",
     access_key="Q3AM3UQ867SPQQA43P2F",
     secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
-    secure=True  # http for False, https for True
+    secure=True,  # http for False, https for True
 )
 
+
 async def main():
     await client.enable_object_legal_hold("my-bucket", "my-object")
 
-loop=asyncio.get_event_loop()
+
+loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
 loop.close()
diff --git a/examples/simple_examples/fget_object.py b/examples/simple_examples/fget_object.py
index 5e5d697..9c433b4 100644
--- a/examples/simple_examples/fget_object.py
+++ b/examples/simple_examples/fget_object.py
@@ -27,9 +27,10 @@
     "play.min.io",
     access_key="Q3AM3UQ867SPQQA43P2F",
     secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
-    secure=True  # http for False, https for True
+    secure=True,  # http for False, https for True
 )
 
+
 async def main():
     # Download data of an object.
     print("example one")
@@ -38,17 +39,22 @@ async def main():
     # Download data of an object of version-ID.
     print("example two")
     await client.fget_object(
-        "my-bucket", "my-object", "my-filename",
+        "my-bucket",
+        "my-object",
+        "my-filename",
         version_id="dfbd25b3-abec-4184-a4e8-5a35a5c1174d",
     )
 
     # Download data of an SSE-C encrypted object.
     print("example three")
     await client.fget_object(
-        "my-bucket", "my-object", "my-filename",
+        "my-bucket",
+        "my-object",
+        "my-filename",
         ssec=SseCustomerKey(b"32byteslongsecretkeymustprovided"),
     )
 
+
 loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
 loop.close()
diff --git a/examples/simple_examples/fput_object.py b/examples/simple_examples/fput_object.py
index 4aa45ef..13d4e38 100644
--- a/examples/simple_examples/fput_object.py
+++ b/examples/simple_examples/fput_object.py
@@ -30,97 +30,129 @@
     "play.min.io",
     access_key="Q3AM3UQ867SPQQA43P2F",
     secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
-    secure=True  # http for False, https for True
+    secure=True,  # http for False, https for True
 )
 
+
 async def main():
     # Upload data.
     print("example one")
     result = await client.fput_object(
-        "my-bucket", "my-object1", "my-filename",
+        "my-bucket",
+        "my-object1",
+        "my-filename",
     )
     print(
         "created {0} object; etag: {1}, version-id: {2}".format(
-            result.object_name, result.etag, result.version_id,
+            result.object_name,
+            result.etag,
+            result.version_id,
         ),
     )
 
     # Upload data with content-type.
     print("example two")
     result = await client.fput_object(
-        "my-bucket", "my-object2", "my-filename",
+        "my-bucket",
+        "my-object2",
+        "my-filename",
         content_type="application/octet-stream",
     )
     print(
         "created {0} object; etag: {1}, version-id: {2}".format(
-            result.object_name, result.etag, result.version_id,
+            result.object_name,
+            result.etag,
+            result.version_id,
         ),
     )
 
     # Upload data with metadata.
     print("example three")
     result = await client.fput_object(
-        "my-bucket", "my-object3", "my-filename",
+        "my-bucket",
+        "my-object3",
+        "my-filename",
         metadata={"Content-Type": "application/octet-stream"},
     )
     print(
         "created {0} object; etag: {1}, version-id: {2}".format(
-            result.object_name, result.etag, result.version_id,
+            result.object_name,
+            result.etag,
+            result.version_id,
         ),
     )
 
     # Upload data with customer key type of server-side encryption.
     print("example four")
     result = await client.fput_object(
-        "my-bucket", "my-object4", "my-filename",
+        "my-bucket",
+        "my-object4",
+        "my-filename",
         sse=SseCustomerKey(b"32byteslongsecretkeymustprovided"),
     )
     print(
         "created {0} object; etag: {1}, version-id: {2}".format(
-            result.object_name, result.etag, result.version_id,
+            result.object_name,
+            result.etag,
+            result.version_id,
         ),
     )
 
     # Upload data with KMS type of server-side encryption.
     print("example five")
     result = await client.fput_object(
-        "my-bucket", "my-object5", "my-filename",
+        "my-bucket",
+        "my-object5",
+        "my-filename",
         sse=SseKMS("KMS-KEY-ID", {"Key1": "Value1", "Key2": "Value2"}),
     )
     print(
         "created {0} object; etag: {1}, version-id: {2}".format(
-            result.object_name, result.etag, result.version_id,
+            result.object_name,
+            result.etag,
+            result.version_id,
         ),
     )
 
     # Upload data with S3 type of server-side encryption.
     print("example six")
     result = await client.fput_object(
-        "my-bucket", "my-object6", "my-filename",
+        "my-bucket",
+        "my-object6",
+        "my-filename",
         sse=SseS3(),
     )
     print(
         "created {0} object; etag: {1}, version-id: {2}".format(
-            result.object_name, result.etag, result.version_id,
+            result.object_name,
+            result.etag,
+            result.version_id,
         ),
     )
 
     # Upload data with tags, retention and legal-hold.
     print("example seven")
     date = datetime.utcnow().replace(
-        hour=0, minute=0, second=0, microsecond=0,
+        hour=0,
+        minute=0,
+        second=0,
+        microsecond=0,
     ) + timedelta(days=30)
     tags = Tags(for_object=True)
     tags["User"] = "jsmith"
     result = await client.fput_object(
-        "my-bucket", "my-object7", "my-filename",
+        "my-bucket",
+        "my-object7",
+        "my-filename",
         tags=tags,
         retention=Retention(GOVERNANCE, date),
         legal_hold=True,
     )
     print(
         "created {0} object; etag: {1}, version-id: {2}".format(
-            result.object_name, result.etag, result.version_id,
+            result.object_name,
+            result.etag,
+            result.version_id,
         ),
     )
 
@@ -131,10 +163,13 @@ async def main():
     )
     print(
         "created {0} object; etag: {1}, version-id: {2}".format(
-            result.object_name, result.etag, result.version_id,
+            result.object_name,
+            result.etag,
+            result.version_id,
         ),
     )
 
+
 loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
 loop.close()
diff --git a/examples/simple_examples/get_bucket_encryption.py b/examples/simple_examples/get_bucket_encryption.py
index 4b0b104..eccb4f2 100644
--- a/examples/simple_examples/get_bucket_encryption.py
+++ b/examples/simple_examples/get_bucket_encryption.py
@@ -26,13 +26,15 @@
     "play.min.io",
     access_key="Q3AM3UQ867SPQQA43P2F",
     secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
-    secure=True  # http for False, https for True
+    secure=True,  # http for False, https for True
 )
 
+
 async def main():
     config = await client.get_bucket_encryption("my-bucket")
     print(config)
 
+
 loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
 loop.close()
diff --git a/examples/simple_examples/get_bucket_lifecycle.py b/examples/simple_examples/get_bucket_lifecycle.py
index 566c79e..1b4c725 100644
--- a/examples/simple_examples/get_bucket_lifecycle.py
+++ b/examples/simple_examples/get_bucket_lifecycle.py
@@ -26,13 +26,15 @@
     "play.min.io",
     access_key="Q3AM3UQ867SPQQA43P2F",
     secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
-    secure=True  # http for False, https for True
+    secure=True,  # http for False, https for True
 )
 
+
 async def main():
     config = await client.get_bucket_lifecycle("my-bucket")
     print(config)
 
+
 loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
 loop.close()
diff --git a/examples/simple_examples/get_bucket_notification.py b/examples/simple_examples/get_bucket_notification.py
index 1740a75..9fe3550 100644
--- a/examples/simple_examples/get_bucket_notification.py
+++ b/examples/simple_examples/get_bucket_notification.py
@@ -26,13 +26,15 @@
     "play.min.io",
     access_key="Q3AM3UQ867SPQQA43P2F",
     secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
-    secure=True  # http for False, https for True
+    secure=True,  # http for False, https for True
 )
 
+
 async def main():
     config = await client.get_bucket_notification("my-bucket")
     print(config)
 
+
 loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
 loop.close()
diff --git a/examples/simple_examples/get_bucket_policy.py b/examples/simple_examples/get_bucket_policy.py
index 551e250..776eda1 100644
--- a/examples/simple_examples/get_bucket_policy.py
+++ b/examples/simple_examples/get_bucket_policy.py
@@ -26,13 +26,15 @@
     "play.min.io",
     access_key="Q3AM3UQ867SPQQA43P2F",
     secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
-    secure=True  # http for False, https for True
+    secure=True,  # http for False, https for True
 )
 
+
 async def main():
     policy = await client.get_bucket_policy("my-bucket")
     print(policy)
 
+
 loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
 loop.close()
diff --git a/examples/simple_examples/get_bucket_replication.py b/examples/simple_examples/get_bucket_replication.py
index 1921ce3..293e003 100644
--- a/examples/simple_examples/get_bucket_replication.py
+++ b/examples/simple_examples/get_bucket_replication.py
@@ -26,13 +26,15 @@
     "play.min.io",
     access_key="Q3AM3UQ867SPQQA43P2F",
     secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
-    secure=True  # http for False, https for True
+    secure=True,  # http for False, https for True
 )
 
+
 async def main():
     config = await client.get_bucket_replication("my-bucket")
     print(config)
 
+
 loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
 loop.close()
diff --git a/examples/simple_examples/get_bucket_tags.py b/examples/simple_examples/get_bucket_tags.py
index 7e10cc1..87b93a4 100644
--- a/examples/simple_examples/get_bucket_tags.py
+++ b/examples/simple_examples/get_bucket_tags.py
@@ -26,13 +26,15 @@
     "play.min.io",
     access_key="Q3AM3UQ867SPQQA43P2F",
     secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
-    secure=True  # http for False, https for True
+    secure=True,  # http for False, https for True
 )
 
+
 async def main():
     tags = await client.get_bucket_tags("my-bucket")
     print(tags)
 
+
 loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
 loop.close()
diff --git a/examples/simple_examples/get_bucket_versioning.py b/examples/simple_examples/get_bucket_versioning.py
index f230ade..6f930ff 100644
--- a/examples/simple_examples/get_bucket_versioning.py
+++ b/examples/simple_examples/get_bucket_versioning.py
@@ -26,13 +26,15 @@
     "play.min.io",
     access_key="Q3AM3UQ867SPQQA43P2F",
     secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
-    secure=True  # http for False, https for True
+    secure=True,  # http for False, https for True
 )
 
+
 async def main():
     config = await client.get_bucket_versioning("my-bucket")
     print(config.status)
 
+
 loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
 loop.close()
diff --git a/examples/simple_examples/get_object.py b/examples/simple_examples/get_object.py
index 52f1218..bc7e271 100644
--- a/examples/simple_examples/get_object.py
+++ b/examples/simple_examples/get_object.py
@@ -27,35 +27,41 @@
     "play.min.io",
     access_key="Q3AM3UQ867SPQQA43P2F",
     secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
-    secure=True  # http for False, https for True
+    secure=True,  # http for False, https for True
 )
 
+
 async def main():
     try:
         # Get data of an object.
-        print('example one')
+        print("example one")
         response = await client.get_object("my-bucket", "my-object")
         # Read data from response.
 
         # Get data of an object from offset and length.
-        print('example two')
+        print("example two")
         response = await client.get_object(
-            "my-bucket", "my-object", offset=512, length=1024,
+            "my-bucket",
+            "my-object",
+            offset=512,
+            length=1024,
         )
         # Read data from response.
 
         # Get data of an object of version-ID.
-        print('example three')
+        print("example three")
         response = await client.get_object(
-            "my-bucket", "my-object",
+            "my-bucket",
+            "my-object",
             version_id="dfbd25b3-abec-4184-a4e8-5a35a5c1174d",
         )
         # Read data from response.
 
         # Get data of an SSE-C encrypted object.
-        print('example four')
+        print("example four")
         response = await client.get_object(
-            "my-bucket", "my-object",
+            "my-bucket",
+            "my-object",
             ssec=SseCustomerKey(b"32byteslongsecretkeymustprovided"),
         )
         # Read data from response.
@@ -63,6 +69,7 @@ async def main():
         response.close()
         await response.release()
 
+
 loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
 loop.close()
diff --git a/examples/simple_examples/get_object_lock_config.py b/examples/simple_examples/get_object_lock_config.py
index f2ed2e9..1377adc 100644
--- a/examples/simple_examples/get_object_lock_config.py
+++ b/examples/simple_examples/get_object_lock_config.py
@@ -26,13 +26,15 @@
     "play.min.io",
     access_key="Q3AM3UQ867SPQQA43P2F",
     secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
-    secure=True  # http for False, https for True
+    secure=True,  # http for False, https for True
 )
 
+
 async def main():
     config = await client.get_object_lock_config("my-bucket")
     print(config)
 
+
 loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
 loop.close()
diff --git a/examples/simple_examples/get_object_retention.py b/examples/simple_examples/get_object_retention.py
index ba5e1c2..27613c8 100644
--- a/examples/simple_examples/get_object_retention.py
+++ b/examples/simple_examples/get_object_retention.py
@@ -26,13 +26,15 @@
     "play.min.io",
     access_key="Q3AM3UQ867SPQQA43P2F",
     secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
-    secure=True  # http for False, https for True
+    secure=True,  # http for False, https for True
 )
 
+
 async def main():
     config = await client.get_object_retention("my-bucket", "my-object")
     print(config)
 
+
 loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
 loop.close()
diff --git a/examples/simple_examples/get_object_tags.py b/examples/simple_examples/get_object_tags.py
index fe54171..5d801c5 100644
--- a/examples/simple_examples/get_object_tags.py
+++ b/examples/simple_examples/get_object_tags.py
@@ -26,13 +26,15 @@
     "play.min.io",
     access_key="Q3AM3UQ867SPQQA43P2F",
     secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
-    secure=True  # http for False, https for True
+    secure=True,  # http for False, https for True
 )
 
+
 async def main():
     tags = await client.get_object_tags("my-bucket", "my-object")
     print(tags)
 
+
 loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
 loop.close()
diff --git a/examples/simple_examples/get_presigned_url.py b/examples/simple_examples/get_presigned_url.py
index 1deaf98..3e80111 100644
--- a/examples/simple_examples/get_presigned_url.py
+++ b/examples/simple_examples/get_presigned_url.py
@@ -29,23 +29,23 @@ async def main():
         "play.min.io",
         access_key="Q3AM3UQ867SPQQA43P2F",
         secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
-        secure=True  # http for False, https for True
+        secure=True,  # http for False, https for True
     )
     # Get presigned URL string to delete 'my-object' in
     # 'my-bucket' with one day expiry.
-    print('example one')
+    print("example one")
     url = await client.get_presigned_url(
         "DELETE",
         "my-bucket",
         "my-object",
         expires=timedelta(days=1),
     )
-    print('url:', url)
+    print("url:", url)
 
     # Get presigned URL string to upload 'my-object' in
     # 'my-bucket' with response-content-type as application/json
     # and one day expiry.
-    print('example two')
+    print("example two")
     url = await client.get_presigned_url(
         "PUT",
         "my-bucket",
@@ -53,18 +53,18 @@ async def main():
         expires=timedelta(days=1),
         response_headers={"response-content-type": "application/json"},
     )
-    print('url:', url)
+    print("url:", url)
 
     # Get presigned URL string to download 'my-object' in
     # 'my-bucket' with two hours expiry.
-    print('example three')
+    print("example three")
     url = await client.get_presigned_url(
         "GET",
         "my-bucket",
         "my-object",
         expires=timedelta(hours=2),
     )
-    print('url:', url)
+    print("url:", url)
 
     # Get presigned URL string to download 'my-object' in
     # 'my-bucket' with public IP address when using private IP address.
@@ -72,18 +72,18 @@ async def main():
         "127.0.0.1:9000",
         access_key="your access key",
         secret_key="you secret key",
-        secure=False  # http for False, https for True
+        secure=False,  # http for False, https for True
     )
 
-    print('example four')
+    print("example four")
     url = await client.get_presigned_url(
         "GET",
         "my-bucket",
         "my-object",
-        change_host='https://YOURHOST:YOURPORT',
+        change_host="https://YOURHOST:YOURPORT",
     )
-    print('url:', url)
-    
+    print("url:", url)
+
 
 loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
diff --git a/examples/simple_examples/is_object_legal_hold_enabled.py b/examples/simple_examples/is_object_legal_hold_enabled.py
index b145a80..e72cc45 100644
--- a/examples/simple_examples/is_object_legal_hold_enabled.py
+++ b/examples/simple_examples/is_object_legal_hold_enabled.py
@@ -26,15 +26,17 @@
     "play.min.io",
     access_key="Q3AM3UQ867SPQQA43P2F",
     secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
-    secure=True  # http for False, https for True
+    secure=True,  # http for False, https for True
 )
 
+
 async def main():
     if await client.is_object_legal_hold_enabled("my-bucket", "my-object"):
         print("legal hold is enabled on my-object")
     else:
         print("legal hold is not enabled on my-object")
 
+
 loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
 loop.close()
diff --git a/examples/simple_examples/list_buckets.py b/examples/simple_examples/list_buckets.py
index b19ce1a..673adeb 100644
--- a/examples/simple_examples/list_buckets.py
+++ b/examples/simple_examples/list_buckets.py
@@ -26,14 +26,16 @@
     "play.min.io",
     access_key="Q3AM3UQ867SPQQA43P2F",
     secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
-    secure=True  # http for False, https for True
+    secure=True,  # http for False, https for True
 )
 
+
 async def main():
     buckets = await client.list_buckets()
     for bucket in buckets:
         print(bucket.name, bucket.creation_date)
 
+
 loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
 loop.close()
diff --git a/examples/simple_examples/list_objects.py b/examples/simple_examples/list_objects.py
index 13841b4..309d7f3 100644
--- a/examples/simple_examples/list_objects.py
+++ b/examples/simple_examples/list_objects.py
@@ -26,45 +26,51 @@
     "play.min.io",
     access_key="Q3AM3UQ867SPQQA43P2F",
     secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
-    secure=True  # http for False, https for True
+    secure=True,  # http for False, https for True
 )
 
+
 async def main():
     # List objects information.
-    print('example one')
+    print("example one")
     objects = await client.list_objects("my-bucket")
     for obj in objects:
-        print('obj:',obj)
+        print("obj:", obj)
 
     # List objects information whose names starts with "my/prefix/".
-    print('example two')
+    print("example two")
     objects = await client.list_objects("my-bucket", prefix="my/prefix/")
     for obj in objects:
-        print('obj:',obj)
+        print("obj:", obj)
 
     # List objects information recursively.
-    print('example three')
+    print("example three")
     objects = await client.list_objects("my-bucket", recursive=True)
     for obj in objects:
-        print('obj:',obj)
+        print("obj:", obj)
 
     # List objects information recursively whose names starts with
     # "my/prefix/".
-    print('example four')
+    print("example four")
     objects = await client.list_objects(
-        "my-bucket", prefix="my/prefix/", recursive=True,
+        "my-bucket",
+        prefix="my/prefix/",
+        recursive=True,
     )
     for obj in objects:
-        print('obj:',obj)
+        print("obj:", obj)
 
     # List objects information recursively after object name
     # "my/prefix/world/1".
-    print('example five')
+    print("example five")
     objects = await client.list_objects(
-        "my-bucket", recursive=True, start_after="my/prefix/world/1",
+        "my-bucket",
+        recursive=True,
+        start_after="my/prefix/world/1",
     )
     for obj in objects:
-        print('obj:',obj)
+        print("obj:", obj)
+
 
 loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
diff --git a/examples/simple_examples/listen_bucket_notification.py b/examples/simple_examples/listen_bucket_notification.py
index b343d06..e26027e 100644
--- a/examples/simple_examples/listen_bucket_notification.py
+++ b/examples/simple_examples/listen_bucket_notification.py
@@ -27,9 +27,10 @@
     "play.min.io",
     access_key="Q3AM3UQ867SPQQA43P2F",
     secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
-    secure=True  # http for False, https for True
+    secure=True,  # http for False, https for True
 )
 
+
 async def main():
     events = await client.listen_bucket_notification(
         "my-bucket",
@@ -37,7 +38,8 @@ async def main():
         events=["s3:ObjectCreated:*", "s3:ObjectRemoved:*"],
     )
     async for event in events:
-        print('event:',event)
+        print("event:", event)
+
 
 loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
diff --git a/examples/simple_examples/make_bucket.py b/examples/simple_examples/make_bucket.py
index 559ec58..36710d4 100644
--- a/examples/simple_examples/make_bucket.py
+++ b/examples/simple_examples/make_bucket.py
@@ -26,22 +26,24 @@
     "play.min.io",
     access_key="Q3AM3UQ867SPQQA43P2F",
     secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
-    secure=True
+    secure=True,
 )
 
+
 async def main():
     # Create bucket.
-    print('example one')
+    print("example one")
     await client.make_bucket("my-bucket1")
 
     # Create bucket on specific region.
-    print('example two')
+    print("example two")
     await client.make_bucket("my-bucket2", "us-east-1")
 
     # Create bucket with object-lock feature on specific region.
-    print('example three')
+    print("example three")
     await client.make_bucket("my-bucket3", "us-east-1", object_lock=True)
 
+
 loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
 loop.close()
diff --git a/examples/simple_examples/minio_with_assume_role_provider.py b/examples/simple_examples/minio_with_assume_role_provider.py
index a74e3a9..ffcd1ca 100644
--- a/examples/simple_examples/minio_with_assume_role_provider.py
+++ b/examples/simple_examples/minio_with_assume_role_provider.py
@@ -58,13 +58,15 @@
     external_id=external_id,
 )
 
-client = Minio("MINIO-HOST:MINIO-PORT", secure = False, credentials=provider)
+client = Minio("MINIO-HOST:MINIO-PORT", secure=False, credentials=provider)
+
 
 async def main():
     # Get information of an object.
     stat = await client.stat_object("my-bucket", "my-object")
     print(stat)
 
+
 loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
 loop.close()
diff --git a/examples/simple_examples/minio_with_aws_config_provider.py b/examples/simple_examples/minio_with_aws_config_provider.py
index c89e6ac..480da19 100644
--- a/examples/simple_examples/minio_with_aws_config_provider.py
+++ b/examples/simple_examples/minio_with_aws_config_provider.py
@@ -25,11 +25,13 @@
 
 client = Minio("s3.amazonaws.com", credentials=AWSConfigProvider())
 
+
 async def main():
     # Get information of an object.
     stat = await client.stat_object("my-bucket", "my-object")
     print(stat)
 
+
 loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
 loop.close()
diff --git a/examples/simple_examples/minio_with_certificate_identity_provider.py b/examples/simple_examples/minio_with_certificate_identity_provider.py
index 538acd4..cb885b5 100644
--- a/examples/simple_examples/minio_with_certificate_identity_provider.py
+++ b/examples/simple_examples/minio_with_certificate_identity_provider.py
@@ -33,16 +33,20 @@
 key_file = "/path/to/client.key"
 
 provider = CertificateIdentityProvider(
-    sts_endpoint, cert_file=cert_file, key_file=key_file,
+    sts_endpoint,
+    cert_file=cert_file,
+    key_file=key_file,
 )
 
 client = Minio("MINIO-HOST:MINIO-PORT", credentials=provider)
 
+
 async def main():
     # Get information of an object.
     stat = await client.stat_object("my-bucket", "my-object")
     print(stat)
 
+
 loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
 loop.close()
diff --git a/examples/simple_examples/minio_with_chained_provider.py b/examples/simple_examples/minio_with_chained_provider.py
index 33aa219..644d1fc 100644
--- a/examples/simple_examples/minio_with_chained_provider.py
+++ b/examples/simple_examples/minio_with_chained_provider.py
@@ -24,7 +24,12 @@
 # 'providers' list
 
 from miniopy_async import Minio
-from miniopy_async.credentials import (AWSConfigProvider, ChainedProvider, EnvAWSProvider, IamAwsProvider)
+from miniopy_async.credentials import (
+    AWSConfigProvider,
+    ChainedProvider,
+    EnvAWSProvider,
+    IamAwsProvider,
+)
 import asyncio
 
 client = Minio(
@@ -35,14 +40,16 @@
             AWSConfigProvider(),
             EnvAWSProvider(),
         ]
-    )
+    ),
 )
 
+
 async def main():
     # Get information of an object.
     stat = await client.stat_object("my-bucket", "my-object")
     print(stat)
 
+
 loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
 loop.close()
diff --git a/examples/simple_examples/minio_with_client_grants_provider.py b/examples/simple_examples/minio_with_client_grants_provider.py
index c419175..eaa1f3d 100644
--- a/examples/simple_examples/minio_with_client_grants_provider.py
+++ b/examples/simple_examples/minio_with_client_grants_provider.py
@@ -42,8 +42,7 @@ def get_jwt(client_id, client_secret, idp_endpoint):
 
 # IDP endpoint.
 idp_endpoint = (
-    "https://IDP-HOST:IDP-PORT/auth/realms/master"
-    "/protocol/openid-connect/token"
+    "https://IDP-HOST:IDP-PORT/auth/realms/master" "/protocol/openid-connect/token"
 )
 
 # Client-ID to fetch JWT.
@@ -56,16 +55,19 @@ def get_jwt(client_id, client_secret, idp_endpoint):
 sts_endpoint = "http://STS-HOST:STS-PORT/"
 
 provider = ClientGrantsProvider(
-    lambda: get_jwt(client_id, client_secret, idp_endpoint), sts_endpoint,
+    lambda: get_jwt(client_id, client_secret, idp_endpoint),
+    sts_endpoint,
 )
 
 client = Minio("MINIO-HOST:MINIO-PORT", credentials=provider)
 
+
 async def main():
     # Get information of an object.
     stat = await client.stat_object("my-bucket", "my-object")
     print(stat)
 
+
 loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
 loop.close()
diff --git a/examples/simple_examples/minio_with_env_aws_provider.py b/examples/simple_examples/minio_with_env_aws_provider.py
index 5740a2c..4b8a071 100644
--- a/examples/simple_examples/minio_with_env_aws_provider.py
+++ b/examples/simple_examples/minio_with_env_aws_provider.py
@@ -25,11 +25,13 @@
 
 client = Minio("s3.amazonaws.com", credentials=EnvAWSProvider())
 
+
 async def main():
     # Get information of an object.
     stat = await client.stat_object("my-bucket", "my-object")
     print(stat)
 
+
 loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
 loop.close()
diff --git a/examples/simple_examples/minio_with_env_minio_provider.py b/examples/simple_examples/minio_with_env_minio_provider.py
index 132aa4d..03f66cf 100644
--- a/examples/simple_examples/minio_with_env_minio_provider.py
+++ b/examples/simple_examples/minio_with_env_minio_provider.py
@@ -25,11 +25,13 @@
 
 client = Minio("MINIO-HOST:MINIO-PORT", credentials=EnvMinioProvider())
 
+
 async def main():
     # Get information of an object.
     stat = await client.stat_object("my-bucket", "my-object")
     print(stat)
 
+
 loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
 loop.close()
diff --git a/examples/simple_examples/minio_with_iam_aws_provider.py b/examples/simple_examples/minio_with_iam_aws_provider.py
index 47bb073..d09118c 100644
--- a/examples/simple_examples/minio_with_iam_aws_provider.py
+++ b/examples/simple_examples/minio_with_iam_aws_provider.py
@@ -25,12 +25,13 @@
 
 client = Minio("s3.amazonaws.com", credentials=IamAwsProvider())
 
+
 async def main():
     # Get information of an object.
     stat = await client.stat_object("my-bucket", "my-object")
     print(stat)
 
+
 loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
 loop.close()
-
diff --git a/examples/simple_examples/minio_with_ldap_identity_provider.py b/examples/simple_examples/minio_with_ldap_identity_provider.py
index e31b232..8a294d2 100644
--- a/examples/simple_examples/minio_with_ldap_identity_provider.py
+++ b/examples/simple_examples/minio_with_ldap_identity_provider.py
@@ -36,11 +36,13 @@
 
 client = Minio("MINIO-HOST:MINIO-PORT", credentials=provider)
 
+
 async def main():
     # Get information of an object.
     stat = await client.stat_object("my-bucket", "my-object")
     print(stat)
 
+
 loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
 loop.close()
diff --git a/examples/simple_examples/minio_with_minio_client_config_provider.py b/examples/simple_examples/minio_with_minio_client_config_provider.py
index 9fbb6e0..af79ea0 100644
--- a/examples/simple_examples/minio_with_minio_client_config_provider.py
+++ b/examples/simple_examples/minio_with_minio_client_config_provider.py
@@ -24,14 +24,17 @@
 import asyncio
 
 client = Minio(
-    "MINIO-HOST:MINIO-PORT", credentials=MinioClientConfigProvider(),
+    "MINIO-HOST:MINIO-PORT",
+    credentials=MinioClientConfigProvider(),
 )
 
+
 async def main():
     # Get information of an object.
     stat = await client.stat_object("my-bucket", "my-object")
     print(stat)
 
+
 loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
 loop.close()
diff --git a/examples/simple_examples/minio_with_web_identity_provider.py b/examples/simple_examples/minio_with_web_identity_provider.py
index e3cb328..eab190f 100644
--- a/examples/simple_examples/minio_with_web_identity_provider.py
+++ b/examples/simple_examples/minio_with_web_identity_provider.py
@@ -43,8 +43,7 @@ def get_jwt(client_id, client_secret, idp_client_id, idp_endpoint):
 
 # IDP endpoint.
 idp_endpoint = (
-    "https://IDP-HOST:IDP-PORT/auth/realms/master"
-    "/protocol/openid-connect/token"
+    "https://IDP-HOST:IDP-PORT/auth/realms/master" "/protocol/openid-connect/token"
 )
 
 # Client-ID to fetch JWT.
@@ -74,11 +73,13 @@ def get_jwt(client_id, client_secret, idp_client_id, idp_endpoint):
 
 client = Minio("MINIO-HOST:MINIO-PORT", credentials=provider)
 
+
 async def main():
     # Get information of an object.
     stat = await client.stat_object("my-bucket", "my-object")
     print(stat)
 
+
 loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
 loop.close()
diff --git a/examples/simple_examples/presigned_get_object.py b/examples/simple_examples/presigned_get_object.py
index e4f2656..ae64083 100644
--- a/examples/simple_examples/presigned_get_object.py
+++ b/examples/simple_examples/presigned_get_object.py
@@ -23,27 +23,30 @@
 from miniopy_async import Minio
 import asyncio
 
+
 async def main():
     client = Minio(
         "play.min.io",
         access_key="Q3AM3UQ867SPQQA43P2F",
         secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
-        secure=True  # http for False, https for True
+        secure=True,  # http for False, https for True
     )
 
     # Get presigned URL string to download 'my-object' in
     # 'my-bucket' with default expiry (i.e. 7 days).
-    print('example one')
+    print("example one")
     url = await client.presigned_get_object("my-bucket", "my-object")
-    print('url:', url)
+    print("url:", url)
 
     # Get presigned URL string to download 'my-object' in
     # 'my-bucket' with two hours expiry.
-    print('example two')
+    print("example two")
     url = await client.presigned_get_object(
-        "my-bucket", "my-object", expires=timedelta(hours=2),
+        "my-bucket",
+        "my-object",
+        expires=timedelta(hours=2),
     )
-    print('url:', url)
+    print("url:", url)
 
     # Get presigned URL string to download 'my-object' in
     # 'my-bucket' with public IP address when using private IP address.
@@ -51,16 +54,17 @@ async def main():
         "127.0.0.1:9000",
         access_key="your access key",
         secret_key="you secret key",
-        secure=False  # http for False, https for True
+        secure=False,  # http for False, https for True
     )
 
-    print('example three')
+    print("example three")
     url = await client.presigned_get_object(
         "my-bucket",
         "my-object",
-        change_host='https://YOURHOST:YOURPORT',
+        change_host="https://YOURHOST:YOURPORT",
     )
-    print('url:', url)
+    print("url:", url)
+
 
 loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
diff --git a/examples/simple_examples/presigned_post_policy.py b/examples/simple_examples/presigned_post_policy.py
index 5355a2e..9ce16cf 100644
--- a/examples/simple_examples/presigned_post_policy.py
+++ b/examples/simple_examples/presigned_post_policy.py
@@ -28,25 +28,26 @@
     "play.min.io",
     access_key="Q3AM3UQ867SPQQA43P2F",
     secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
-    secure=True  # http for False, https for True
+    secure=True,  # http for False, https for True
 )
 
 policy = PostPolicy(
-    "my-bucket", datetime.utcnow() + timedelta(days=10),
+    "my-bucket",
+    datetime.utcnow() + timedelta(days=10),
 )
 policy.add_starts_with_condition("key", "my/object/prefix/")
-policy.add_content_length_range_condition(1*1024*1024, 10*1024*1024)
+policy.add_content_length_range_condition(1 * 1024 * 1024, 10 * 1024 * 1024)
+
 
 async def main():
     form_data = await client.presigned_post_policy(policy)
     curl_cmd = (
-        "curl -X POST "
-        "https://play.min.io/my-bucket "
-        "{0} -F file=@<FILE>"
+        "curl -X POST " "https://play.min.io/my-bucket " "{0} -F file=@<FILE>"
     ).format(
         " ".join(["-F {0}={1}".format(k, v) for k, v in form_data.items()]),
     )
-    print('curl_cmd:',curl_cmd)
+    print("curl_cmd:", curl_cmd)
+
 
 loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
diff --git a/examples/simple_examples/presigned_put_object.py b/examples/simple_examples/presigned_put_object.py
index 87a9858..1fe550e 100644
--- a/examples/simple_examples/presigned_put_object.py
+++ b/examples/simple_examples/presigned_put_object.py
@@ -23,25 +23,28 @@
 from miniopy_async import Minio
 import asyncio
 
+
 async def main():
     client = Minio(
         "play.min.io",
         access_key="Q3AM3UQ867SPQQA43P2F",
         secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
-        secure=True  # http for False, https for True
+        secure=True,  # http for False, https for True
     )
 
     # Get presigned URL string to upload data to 'my-object' in
     # 'my-bucket' with default expiry (i.e. 7 days).
     url = await client.presigned_put_object("my-bucket", "my-object")
-    print('url:', url)
+    print("url:", url)
 
     # Get presigned URL string to upload data to 'my-object' in
     # 'my-bucket' with two hours expiry.
     url = await client.presigned_put_object(
-        "my-bucket", "my-object", expires=timedelta(hours=2),
+        "my-bucket",
+        "my-object",
+        expires=timedelta(hours=2),
     )
-    print('url:', url)
+    print("url:", url)
 
     # Get presigned URL string to upload data to 'my-object' in
     # 'my-bucket' with public IP address when using private IP address.
@@ -49,16 +52,17 @@ async def main():
         "127.0.0.1:9000",
         access_key="your access key",
         secret_key="you secret key",
-        secure=False  # http for False, https for True
+        secure=False,  # http for False, https for True
     )
 
-    print('example three')
+    print("example three")
     url = await client.presigned_put_object(
         "my-bucket",
         "my-object",
-        change_host='https://YOURHOST:YOURPORT',
+        change_host="https://YOURHOST:YOURPORT",
     )
-    print('url:', url)
+    print("url:", url)
+
 
 loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
diff --git a/examples/simple_examples/put_object.py b/examples/simple_examples/put_object.py
index 64e5d4d..3543e8d 100644
--- a/examples/simple_examples/put_object.py
+++ b/examples/simple_examples/put_object.py
@@ -32,125 +32,177 @@
     "play.min.io",
     access_key="Q3AM3UQ867SPQQA43P2F",
     secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
-    secure=True  # http for False, https for True
+    secure=True,  # http for False, https for True
 )
 
+
 async def main():
     # Upload data.
-    print('example one')
+    print("example one")
     result = await client.put_object(
-        "my-bucket", "my-object", io.BytesIO(b"hello"), 5,
+        "my-bucket",
+        "my-object",
+        io.BytesIO(b"hello"),
+        5,
     )
     print(
         "created {0} object; etag: {1}, version-id: {2}".format(
-            result.object_name, result.etag, result.version_id,
+            result.object_name,
+            result.etag,
+            result.version_id,
         ),
     )
 
     # Upload unknown sized data.
-    print('example two')
+    print("example two")
     data = urlopen(
         "https://raw.githubusercontent.com/hlf20010508/miniopy-async/master/README.md",
     )
     result = await client.put_object(
-        "my-bucket", "my-object", data, length=-1, part_size=10*1024*1024,
+        "my-bucket",
+        "my-object",
+        data,
+        length=-1,
+        part_size=10 * 1024 * 1024,
     )
     print(
         "created {0} object; etag: {1}, version-id: {2}".format(
-            result.object_name, result.etag, result.version_id,
+            result.object_name,
+            result.etag,
+            result.version_id,
         ),
     )
 
     # Upload data with content-type.
-    print('example three')
+    print("example three")
     result = await client.put_object(
-        "my-bucket", "my-object", io.BytesIO(b"hello"), 5,
+        "my-bucket",
+        "my-object",
+        io.BytesIO(b"hello"),
+        5,
         content_type="application/csv",
     )
     print(
         "created {0} object; etag: {1}, version-id: {2}".format(
-            result.object_name, result.etag, result.version_id,
+            result.object_name,
+            result.etag,
+            result.version_id,
         ),
     )
 
     # Upload data with metadata.
-    print('example four')
+    print("example four")
     result = await client.put_object(
-        "my-bucket", "my-object", io.BytesIO(b"hello"), 5,
+        "my-bucket",
+        "my-object",
+        io.BytesIO(b"hello"),
+        5,
         metadata={"Content-Type": "application/octet-stream"},
     )
     print(
         "created {0} object; etag: {1}, version-id: {2}".format(
-            result.object_name, result.etag, result.version_id,
+            result.object_name,
+            result.etag,
+            result.version_id,
         ),
     )
 
     # Upload data with customer key type of server-side encryption.
-    print('example five')
+    print("example five")
     result = await client.put_object(
-        "my-bucket", "my-object", io.BytesIO(b"hello"), 5,
+        "my-bucket",
+        "my-object",
+        io.BytesIO(b"hello"),
+        5,
         sse=SseCustomerKey(b"32byteslongsecretkeymustprovided"),
     )
     print(
         "created {0} object; etag: {1}, version-id: {2}".format(
-            result.object_name, result.etag, result.version_id,
+            result.object_name,
+            result.etag,
+            result.version_id,
         ),
     )
 
     # Upload data with KMS type of server-side encryption.
-    print('example six')
+    print("example six")
     result = await client.put_object(
-        "my-bucket", "my-object", io.BytesIO(b"hello"), 5,
+        "my-bucket",
+        "my-object",
+        io.BytesIO(b"hello"),
+        5,
         sse=SseKMS("KMS-KEY-ID", {"Key1": "Value1", "Key2": "Value2"}),
     )
     print(
         "created {0} object; etag: {1}, version-id: {2}".format(
-            result.object_name, result.etag, result.version_id,
+            result.object_name,
+            result.etag,
+            result.version_id,
         ),
     )
 
     # Upload data with S3 type of server-side encryption.
-    print('example seven')
+    print("example seven")
     result = await client.put_object(
-        "my-bucket", "my-object", io.BytesIO(b"hello"), 5,
+        "my-bucket",
+        "my-object",
+        io.BytesIO(b"hello"),
+        5,
         sse=SseS3(),
     )
     print(
         "created {0} object; etag: {1}, version-id: {2}".format(
-            result.object_name, result.etag, result.version_id,
+            result.object_name,
+            result.etag,
+            result.version_id,
         ),
     )
 
     # Upload data with tags, retention and legal-hold.
-    print('example eight')
+    print("example eight")
     date = datetime.utcnow().replace(
-        hour=0, minute=0, second=0, microsecond=0,
+        hour=0,
+        minute=0,
+        second=0,
+        microsecond=0,
     ) + timedelta(days=30)
     tags = Tags(for_object=True)
     tags["User"] = "jsmith"
     result = await client.put_object(
-        "my-bucket", "my-object", io.BytesIO(b"hello"), 5,
+        "my-bucket",
+        "my-object",
+        io.BytesIO(b"hello"),
+        5,
         tags=tags,
         retention=Retention(GOVERNANCE, date),
         legal_hold=True,
     )
     print(
         "created {0} object; etag: {1}, version-id: {2}".format(
-            result.object_name, result.etag, result.version_id,
+            result.object_name,
+            result.etag,
+            result.version_id,
         ),
     )
 
     # Upload data with showing progress status.
-    print('example nine')
+    print("example nine")
     result = await client.put_object(
-        "transfer", "my-object", io.BytesIO(b"helloworld"*2000000), 20000000, progress=True
+        "transfer",
+        "my-object",
+        io.BytesIO(b"helloworld" * 2000000),
+        20000000,
+        progress=True,
     )
     print(
         "created {0} object; etag: {1}, version-id: {2}".format(
-            result.object_name, result.etag, result.version_id,
+            result.object_name,
+            result.etag,
+            result.version_id,
         ),
     )
 
+
 loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
 loop.close()
diff --git a/examples/simple_examples/remove_bucket.py b/examples/simple_examples/remove_bucket.py
index 2d98402..eacf5e5 100644
--- a/examples/simple_examples/remove_bucket.py
+++ b/examples/simple_examples/remove_bucket.py
@@ -26,12 +26,14 @@
     "play.min.io",
     access_key="Q3AM3UQ867SPQQA43P2F",
     secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
-    secure=True  # http for False, https for True
+    secure=True,  # http for False, https for True
 )
 
+
 async def main():
     await client.remove_bucket("my-bucket")
 
+
 loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
 loop.close()
diff --git a/examples/simple_examples/remove_object.py b/examples/simple_examples/remove_object.py
index 46501e0..7a08b54 100644
--- a/examples/simple_examples/remove_object.py
+++ b/examples/simple_examples/remove_object.py
@@ -26,21 +26,24 @@
     "play.min.io",
     access_key="Q3AM3UQ867SPQQA43P2F",
     secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
-    secure=True  # http for False, https for True
+    secure=True,  # http for False, https for True
 )
 
+
 async def main():
     # Remove object.
-    print('example one')
+    print("example one")
     await client.remove_object("my-bucket", "my-object")
 
     # Remove version of an object.
-    print('example two')
+    print("example two")
     await client.remove_object(
-        "my-bucket", "my-object",
+        "my-bucket",
+        "my-object",
         version_id="dfbd25b3-abec-4184-a4e8-5a35a5c1174d",
     )
 
+
 loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
-loop.close()
\ No newline at end of file
+loop.close()
diff --git a/examples/simple_examples/remove_objects.py b/examples/simple_examples/remove_objects.py
index 9509fdb..8796e24 100644
--- a/examples/simple_examples/remove_objects.py
+++ b/examples/simple_examples/remove_objects.py
@@ -27,12 +27,13 @@
     "play.min.io",
     access_key="Q3AM3UQ867SPQQA43P2F",
     secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
-    secure=True  # http for False, https for True
+    secure=True,  # http for False, https for True
 )
 
+
 async def main():
     # Remove list of objects.
-    print('example one')
+    print("example one")
     errors = await client.remove_objects(
         "my-bucket",
         [
@@ -45,18 +46,16 @@ async def main():
         print("error occured when deleting object", error)
 
     # Remove a prefix recursively.
-    print('example two')
-    delete_object_list = [DeleteObject(obj.object_name)
-        for obj in await client.list_objects(
-            "my-bucket",
-            "my/prefix/",
-            recursive=True
-        )
+    print("example two")
+    delete_object_list = [
+        DeleteObject(obj.object_name)
+        for obj in await client.list_objects("my-bucket", "my/prefix/", recursive=True)
     ]
     errors = await client.remove_objects("my-bucket", delete_object_list)
     for error in errors:
         print("error occured when deleting object", error)
 
+
 loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
 loop.close()
diff --git a/examples/simple_examples/select_object_content.py b/examples/simple_examples/select_object_content.py
index 1eae667..5c679a6 100644
--- a/examples/simple_examples/select_object_content.py
+++ b/examples/simple_examples/select_object_content.py
@@ -20,7 +20,11 @@
 # Date: 2022-07-11
 
 from miniopy_async import Minio
-from miniopy_async.select import (CSVInputSerialization, CSVOutputSerialization, SelectRequest)
+from miniopy_async.select import (
+    CSVInputSerialization,
+    CSVOutputSerialization,
+    SelectRequest,
+)
 from aiostream.stream import list as alist
 import asyncio
 
@@ -28,9 +32,10 @@
     "play.min.io",
     access_key="Q3AM3UQ867SPQQA43P2F",
     secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
-    secure=True  # http for False, https for True
+    secure=True,  # http for False, https for True
 )
 
+
 async def main():
     result = await client.select_object_content(
         "my-bucket",
@@ -43,10 +48,11 @@ async def main():
         ),
     )
     print(type(result.stream()))
-    print('data:')
+    print("data:")
     for data in await alist(result.stream()):
         print(data.decode())
-    print('status:',result.stats())
+    print("status:", result.stats())
+
 
 loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
diff --git a/examples/simple_examples/set_bucket_encryption.py b/examples/simple_examples/set_bucket_encryption.py
index 448fcfa..b60fd8f 100644
--- a/examples/simple_examples/set_bucket_encryption.py
+++ b/examples/simple_examples/set_bucket_encryption.py
@@ -27,14 +27,17 @@
     "play.min.io",
     access_key="Q3AM3UQ867SPQQA43P2F",
     secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
-    secure=True  # http for False, https for True
+    secure=True,  # http for False, https for True
 )
 
+
 async def main():
     await client.set_bucket_encryption(
-        "my-bucket", SSEConfig(Rule.new_sse_s3_rule()),
+        "my-bucket",
+        SSEConfig(Rule.new_sse_s3_rule()),
     )
 
+
 loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
 loop.close()
diff --git a/examples/simple_examples/set_bucket_lifecycle.py b/examples/simple_examples/set_bucket_lifecycle.py
index d4b8266..ae184b2 100644
--- a/examples/simple_examples/set_bucket_lifecycle.py
+++ b/examples/simple_examples/set_bucket_lifecycle.py
@@ -28,7 +28,7 @@
     "play.min.io",
     access_key="Q3AM3UQ867SPQQA43P2F",
     secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
-    secure=True  # http for False, https for True
+    secure=True,  # http for False, https for True
 )
 
 config = LifecycleConfig(
@@ -48,9 +48,11 @@
     ],
 )
 
+
 async def main():
     await client.set_bucket_lifecycle("my-bucket", config)
 
+
 loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
 loop.close()
diff --git a/examples/simple_examples/set_bucket_notification.py b/examples/simple_examples/set_bucket_notification.py
index 88e2e6e..95d2449 100644
--- a/examples/simple_examples/set_bucket_notification.py
+++ b/examples/simple_examples/set_bucket_notification.py
@@ -20,14 +20,18 @@
 # Date: 2022-07-11
 
 from miniopy_async import Minio
-from miniopy_async.notificationconfig import (NotificationConfig, PrefixFilterRule, QueueConfig)
+from miniopy_async.notificationconfig import (
+    NotificationConfig,
+    PrefixFilterRule,
+    QueueConfig,
+)
 import asyncio
 
 client = Minio(
     "play.min.io",
     access_key="Q3AM3UQ867SPQQA43P2F",
     secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
-    secure=True  # http for False, https for True
+    secure=True,  # http for False, https for True
 )
 
 config = NotificationConfig(
@@ -41,9 +45,11 @@
     ],
 )
 
+
 async def main():
     await client.set_bucket_notification("my-bucket", config)
 
+
 loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
-loop.close()
\ No newline at end of file
+loop.close()
diff --git a/examples/simple_examples/set_bucket_policy.py b/examples/simple_examples/set_bucket_policy.py
index bd98743..9621680 100644
--- a/examples/simple_examples/set_bucket_policy.py
+++ b/examples/simple_examples/set_bucket_policy.py
@@ -27,12 +27,13 @@
     "play.min.io",
     access_key="Q3AM3UQ867SPQQA43P2F",
     secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
-    secure=True  # http for False, https for True
+    secure=True,  # http for False, https for True
 )
 
+
 async def main():
     # Example anonymous read-only bucket policy.
-    print('example one')
+    print("example one")
     policy = {
         "Version": "2012-10-17",
         "Statement": [
@@ -53,7 +54,7 @@ async def main():
     await client.set_bucket_policy("my-bucket", json.dumps(policy))
 
     # Example anonymous read-write bucket policy.
-    print('example two')
+    print("example two")
     policy = {
         "Version": "2012-10-17",
         "Statement": [
@@ -83,6 +84,7 @@ async def main():
     }
     await client.set_bucket_policy("my-bucket", json.dumps(policy))
 
+
 loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
 loop.close()
diff --git a/examples/simple_examples/set_bucket_replication.py b/examples/simple_examples/set_bucket_replication.py
index 626cb17..bd43b45 100644
--- a/examples/simple_examples/set_bucket_replication.py
+++ b/examples/simple_examples/set_bucket_replication.py
@@ -20,17 +20,26 @@
 # Date: 2022-07-11
 
 from miniopy_async import Minio
-from miniopy_async.commonconfig import DISABLED, ENABLED, AndOperator, Filter
-from miniopy_async.replicationconfig import (DeleteMarkerReplication, Destination, ReplicationConfig, Rule)
+from miniopy_async.commonconfig import DISABLED, ENABLED, AndOperator, Filter, Tags
+from miniopy_async.replicationconfig import (
+    DeleteMarkerReplication,
+    Destination,
+    ReplicationConfig,
+    Rule,
+)
 import asyncio
 
 client = Minio(
     "play.min.io",
     access_key="Q3AM3UQ867SPQQA43P2F",
     secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
-    secure=True  # http for False, https for True
+    secure=True,  # http for False, https for True
 )
 
+bucket_tags = Tags.new_bucket_tags()
+bucket_tags["Project"] = "Project One"
+bucket_tags["User"] = "jsmith"
+
 config = ReplicationConfig(
     "REPLACE-WITH-ACTUAL-ROLE",
     [
@@ -45,7 +54,7 @@
             rule_filter=Filter(
                 AndOperator(
                     "TaxDocs",
-                    {"key1": "value1", "key2": "value2"},
+                    bucket_tags,
                 ),
             ),
             rule_id="rule1",
@@ -54,9 +63,11 @@
     ],
 )
 
+
 async def main():
     await client.set_bucket_replication("my-bucket", config)
 
+
 loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
 loop.close()
diff --git a/examples/simple_examples/set_bucket_tags.py b/examples/simple_examples/set_bucket_tags.py
index cfb568a..ccacbaf 100644
--- a/examples/simple_examples/set_bucket_tags.py
+++ b/examples/simple_examples/set_bucket_tags.py
@@ -27,16 +27,18 @@
     "play.min.io",
     access_key="Q3AM3UQ867SPQQA43P2F",
     secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
-    secure=True  # http for False, https for True
+    secure=True,  # http for False, https for True
 )
 
 tags = Tags.new_bucket_tags()
 tags["Project"] = "Project One"
 tags["User"] = "jsmith"
 
+
 async def main():
     await client.set_bucket_tags("my-bucket", tags)
 
+
 loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
 loop.close()
diff --git a/examples/simple_examples/set_bucket_versioning.py b/examples/simple_examples/set_bucket_versioning.py
index cf70c5d..06d22be 100644
--- a/examples/simple_examples/set_bucket_versioning.py
+++ b/examples/simple_examples/set_bucket_versioning.py
@@ -28,12 +28,14 @@
     "play.min.io",
     access_key="Q3AM3UQ867SPQQA43P2F",
     secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
-    secure=True  # http for False, https for True
+    secure=True,  # http for False, https for True
 )
 
+
 async def main():
     await client.set_bucket_versioning("my-bucket", VersioningConfig(ENABLED))
 
+
 loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
 loop.close()
diff --git a/examples/simple_examples/set_object_lock_config.py b/examples/simple_examples/set_object_lock_config.py
index 96288c6..d39d3d6 100644
--- a/examples/simple_examples/set_object_lock_config.py
+++ b/examples/simple_examples/set_object_lock_config.py
@@ -28,14 +28,16 @@
     "play.min.io",
     access_key="Q3AM3UQ867SPQQA43P2F",
     secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
-    secure=True  # http for False, https for True
+    secure=True,  # http for False, https for True
 )
 
 config = ObjectLockConfig(GOVERNANCE, 15, DAYS)
 
+
 async def main():
     await client.set_object_lock_config("my-bucket", config)
 
+
 loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
 loop.close()
diff --git a/examples/simple_examples/set_object_retention.py b/examples/simple_examples/set_object_retention.py
index 3e4ca89..c35661a 100644
--- a/examples/simple_examples/set_object_retention.py
+++ b/examples/simple_examples/set_object_retention.py
@@ -29,14 +29,16 @@
     "play.min.io",
     access_key="Q3AM3UQ867SPQQA43P2F",
     secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
-    secure=True  # http for False, https for True
+    secure=True,  # http for False, https for True
 )
 
 config = Retention(GOVERNANCE, datetime.utcnow() + timedelta(days=10))
 
+
 async def main():
     await client.set_object_retention("my-bucket", "my-object", config)
 
+
 loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
 loop.close()
diff --git a/examples/simple_examples/set_object_tags.py b/examples/simple_examples/set_object_tags.py
index d68afa1..3475486 100644
--- a/examples/simple_examples/set_object_tags.py
+++ b/examples/simple_examples/set_object_tags.py
@@ -27,16 +27,18 @@
     "play.min.io",
     access_key="Q3AM3UQ867SPQQA43P2F",
     secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
-    secure=True  # http for False, https for True
+    secure=True,  # http for False, https for True
 )
 
 tags = Tags.new_object_tags()
 tags["Project"] = "Project One"
 tags["User"] = "jsmith"
 
+
 async def main():
     await client.set_object_tags("my-bucket", "my-object", tags)
 
+
 loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
 loop.close()
diff --git a/examples/simple_examples/stat_object.py b/examples/simple_examples/stat_object.py
index ae6d2fe..e6009d3 100644
--- a/examples/simple_examples/stat_object.py
+++ b/examples/simple_examples/stat_object.py
@@ -27,43 +27,50 @@
     "play.min.io",
     access_key="Q3AM3UQ867SPQQA43P2F",
     secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
-    secure=True  # http for False, https for True
+    secure=True,  # http for False, https for True
 )
 
+
 async def main():
     # Get object information.
-    print('example one')
+    print("example one")
     result = await client.stat_object("my-bucket", "my-object")
     print(
         "status: last-modified: {0}, size: {1}".format(
-            result.last_modified, result.size,
+            result.last_modified,
+            result.size,
         ),
     )
 
     # Get object information of version-ID.
-    print('example two')
+    print("example two")
     result = await client.stat_object(
-        "my-bucket", "my-object",
+        "my-bucket",
+        "my-object",
         version_id="dfbd25b3-abec-4184-a4e8-5a35a5c1174d",
     )
     print(
         "status: last-modified: {0}, size: {1}".format(
-            result.last_modified, result.size,
+            result.last_modified,
+            result.size,
         ),
     )
 
     # Get SSE-C encrypted object information.
-    print('example three')
+    print("example three")
     result = await client.stat_object(
-        "my-bucket", "my-object",
+        "my-bucket",
+        "my-object",
         ssec=SseCustomerKey(b"32byteslongsecretkeymustprovided"),
     )
     print(
         "status: last-modified: {0}, size: {1}".format(
-            result.last_modified, result.size,
+            result.last_modified,
+            result.size,
         ),
     )
 
+
 loop = asyncio.get_event_loop()
 loop.run_until_complete(main())
 loop.close()
diff --git a/miniopy_async/__init__.py b/miniopy_async/__init__.py
index bdf6659..41dbdec 100644
--- a/miniopy_async/__init__.py
+++ b/miniopy_async/__init__.py
@@ -45,7 +45,7 @@
 
 __title__ = "miniopy-async"
 __author__ = "L-ING."
-__version__ = "1.12"
+__version__ = "1.13"
 __license__ = "Apache 2.0"
 __copyright__ = "(C) 2022 L-ING <hlf01@icloud.com>"
 
diff --git a/miniopy_async/api.py b/miniopy_async/api.py
index ed30788..3ff5798 100644
--- a/miniopy_async/api.py
+++ b/miniopy_async/api.py
@@ -33,6 +33,7 @@
 import itertools
 import os
 import platform
+
 # import weakref
 from concurrent.futures import ThreadPoolExecutor
 from datetime import timedelta
@@ -55,7 +56,7 @@
     Part,
     PostPolicy,
     parse_copy_object,
-    parse_list_objects
+    parse_list_objects,
 )
 from .deleteobjects import DeleteError, DeleteRequest, DeleteResult
 from .error import InvalidResponseError, S3Error, ServerError
@@ -76,7 +77,7 @@
     makedirs,
     md5sum_hash,
     read_part_data,
-    sha256_hash
+    sha256_hash,
 )
 from .legalhold import LegalHold
 from .lifecycleconfig import LifecycleConfig
@@ -94,8 +95,10 @@
 from .xml import Element, SubElement, findtext, getbytes, marshal, unmarshal
 
 _DEFAULT_USER_AGENT = "MinIO ({os}; {arch}) {lib}/{ver}".format(
-    os=platform.system(), arch=platform.machine(),
-    lib=__title__, ver=__version__,
+    os=platform.system(),
+    arch=platform.machine(),
+    lib=__title__,
+    ver=__version__,
 )
 
 
@@ -147,9 +150,8 @@ def __init__(
         session_token=None,
         secure=True,
         region=None,
-        credentials=None
+        credentials=None,
     ):
-
         self._region_map = dict()
         self._base_url = BaseURL(
             ("https://" if secure else "http://") + endpoint,
@@ -160,13 +162,7 @@ def __init__(
             credentials = StaticProvider(access_key, secret_key, session_token)
         self._provider = credentials
 
-    def _handle_redirect_response(
-        self,
-        method,
-        bucket_name,
-        response,
-        retry=False
-    ):
+    def _handle_redirect_response(self, method, bucket_name, response, retry=False):
         """
         Handle redirect response indicates whether retry HEAD request
         on failure.
@@ -181,8 +177,11 @@ def _handle_redirect_response(
             message += "; use region " + region
 
         if (
-                retry and region and method == "HEAD" and bucket_name and
-                self._region_map.get(bucket_name)
+            retry
+            and region
+            and method == "HEAD"
+            and bucket_name
+            and self._region_map.get(bucket_name)
         ):
             code, message = ("RetryHead", None)
 
@@ -207,9 +206,7 @@ async def _build_headers(self, host, headers, body, credentials):
                 _current_event_loop = asyncio.get_event_loop()
                 _thread_pool_executor = ThreadPoolExecutor(max_workers=16)
                 sha256 = await _current_event_loop.run_in_executor(
-                    _thread_pool_executor,
-                    sha256_hash,
-                    body
+                    _thread_pool_executor, sha256_hash, body
                 )
         else:
             md5sum = None if md5sum_added else md5sum_hash(body)
@@ -244,10 +241,7 @@ async def _url_open(  # pylint: disable=too-many-branches
             query_params=query_params,
         )
         headers, date = await self._build_headers(
-            url.netloc,
-            headers,
-            body,
-            credentials
+            url.netloc, headers, body, credentials
         )
         if credentials:
             headers = sign_v4_s3(
@@ -264,13 +258,11 @@ async def _url_open(  # pylint: disable=too-many-branches
             session = aiohttp.ClientSession()
             # should_attach_finalizer = True
         # else:
-            # should_attach_finalizer = False
+        # should_attach_finalizer = False
 
         response = await session.request(
-            method,
-            urlunsplit(url),
-            data=body,
-            headers=headers)
+            method, urlunsplit(url), data=body, headers=headers
+        )
 
         # if should_attach_finalizer:
         #     _attach_finalizer(response, session, asyncio.get_running_loop())
@@ -294,19 +286,28 @@ async def _url_open(  # pylint: disable=too-many-branches
                 None,
             )
 
-        response_error = S3Error.fromxml(
-            response, response_data
-        ) if response_data else None
+        response_error = (
+            S3Error.fromxml(response, response_data) if response_data else None
+        )
 
         error_map = {
             301: lambda: self._handle_redirect_response(
-                method, bucket_name, response, True,
+                method,
+                bucket_name,
+                response,
+                True,
             ),
             307: lambda: self._handle_redirect_response(
-                method, bucket_name, response, True,
+                method,
+                bucket_name,
+                response,
+                True,
             ),
             400: lambda: self._handle_redirect_response(
-                method, bucket_name, response, True,
+                method,
+                bucket_name,
+                response,
+                True,
             ),
             403: lambda: ("AccessDenied", "Access denied"),
             404: lambda: (
@@ -337,7 +338,7 @@ async def _url_open(  # pylint: disable=too-many-branches
             if not code:
                 raise ServerError(
                     f"server failed with HTTP status code {response.status}",
-                    response.status
+                    response.status,
                 )
             response_error = S3Error(
                 code,
@@ -363,41 +364,77 @@ async def _execute(
         body=None,
         headers=None,
         query_params=None,
+        session=None,
     ):
         """Execute HTTP request."""
         region = await self._get_region(bucket_name, None)
 
         try:
-            return await self._url_open(
-                method,
-                region,
-                bucket_name=bucket_name,
-                object_name=object_name,
-                body=body,
-                headers=headers,
-                query_params=query_params,
-            )
+            if session is None:
+                async with aiohttp.ClientSession() as session:
+                    response = await self._url_open(
+                        method,
+                        region,
+                        bucket_name=bucket_name,
+                        object_name=object_name,
+                        body=body,
+                        headers=headers,
+                        query_params=query_params,
+                        session=session,
+                    )
+                return response
+            else:
+                response = await self._url_open(
+                    method,
+                    region,
+                    bucket_name=bucket_name,
+                    object_name=object_name,
+                    body=body,
+                    headers=headers,
+                    query_params=query_params,
+                    session=session,
+                )
+                return response
         except S3Error as exc:
             if exc.code != "RetryHead":
                 raise
 
         # Retry only once on RetryHead error.
         try:
-            return await self._url_open(
-                method,
-                region,
-                bucket_name=bucket_name,
-                object_name=object_name,
-                body=body,
-                headers=headers,
-                query_params=query_params,
-            )
+            if session is None:
+                async with aiohttp.ClientSession() as session:
+                    response = await self._url_open(
+                        method,
+                        region,
+                        bucket_name=bucket_name,
+                        object_name=object_name,
+                        body=body,
+                        headers=headers,
+                        query_params=query_params,
+                        session=session,
+                    )
+                return response
+            else:
+                async with aiohttp.ClientSession() as session:
+                    response = await self._url_open(
+                        method,
+                        region,
+                        bucket_name=bucket_name,
+                        object_name=object_name,
+                        body=body,
+                        headers=headers,
+                        query_params=query_params,
+                        session=session,
+                    )
+                return response
         except S3Error as exc:
             if exc.code != "RetryHead":
                 raise
 
             code, message = self._handle_redirect_response(
-                method, bucket_name, exc.response,
+                method,
+                bucket_name,
+                exc.response,
             )
             raise exc.copy(code, message)
 
@@ -413,7 +450,8 @@ async def _get_region(self, bucket_name, region):
             if self._base_url.region and self._base_url.region != region:
                 raise ValueError(
                     "region must be {0}, but passed {1}".format(
-                        self._base_url.region, region,
+                        self._base_url.region,
+                        region,
                     ),
                 )
             return region
@@ -429,12 +467,14 @@ async def _get_region(self, bucket_name, region):
             return region
 
         # Execute GetBucketLocation REST API to get region of the bucket.
-        response = await self._url_open(
-            "GET",
-            "us-east-1",
-            bucket_name=bucket_name,
-            query_params={"location": ""},
-        )
+        async with aiohttp.ClientSession() as session:
+            response = await self._url_open(
+                "GET",
+                "us-east-1",
+                bucket_name=bucket_name,
+                query_params={"location": ""},
+                session=session,
+            )
 
         element = ET.fromstring(await response.text())
 
@@ -462,7 +502,9 @@ def set_app_info(self, app_name, app_version):
             raise ValueError("Application name/version cannot be empty.")
 
         self._user_agent = "{0} {1}/{2}".format(
-            _DEFAULT_USER_AGENT, app_name, app_version,
+            _DEFAULT_USER_AGENT,
+            app_name,
+            app_version,
         )
 
     def enable_accelerate_endpoint(self):
@@ -538,6 +580,7 @@ async def main():
         if not isinstance(request, SelectRequest):
             raise ValueError("request must be SelectRequest type")
         body = marshal(request)
+        session = aiohttp.ClientSession()
         response = await self._execute(
             "POST",
             bucket_name=bucket_name,
@@ -545,14 +588,12 @@ async def main():
             body=body,
             headers={"Content-MD5": md5sum_hash(body)},
             query_params={"select": "", "select-type": "2"},
+            session=session,
         )
-        return SelectObjectReader(response)
+        return SelectObjectReader(response, session)
 
     async def make_bucket(
-        self,
-        bucket_name,
-        location='us-east-1',
-        object_lock=False
+        self, bucket_name, location="us-east-1", object_lock=False
     ) -> None:
         """
         Create a bucket with region and object lock.
@@ -600,23 +641,22 @@ async def main():
                     f"but {location} was passed"
                 )
         location = self._base_url.region or location or "us-east-1"
-        headers = (
-            {"x-amz-bucket-object-lock-enabled": "true"}
-            if object_lock else None
-        )
+        headers = {"x-amz-bucket-object-lock-enabled": "true"} if object_lock else None
 
         body = None
         if location != "us-east-1":
             element = Element("CreateBucketConfiguration")
             SubElement(element, "LocationConstraint", location)
             body = getbytes(element)
-        await self._url_open(
-            "PUT",
-            location,
-            bucket_name=bucket_name,
-            body=body,
-            headers=headers,
-        )
+        async with aiohttp.ClientSession() as session:
+            await self._url_open(
+                "PUT",
+                location,
+                bucket_name=bucket_name,
+                body=body,
+                headers=headers,
+                session=session,
+            )
         self._region_map[bucket_name] = location
 
     async def list_buckets(self) -> list:
@@ -645,10 +685,10 @@ async def main():
             loop.run_until_complete(main())
             loop.close()
         """
-
-        response = await self._execute("GET")
-        result = unmarshal(ListAllMyBucketsResult, await response.text())
-        return result.buckets
+        async with aiohttp.ClientSession() as session:
+            response = await self._execute("GET", session=session)
+            result = unmarshal(ListAllMyBucketsResult, await response.text())
+            return result.buckets
 
     async def bucket_exists(self, bucket_name):
         """
@@ -743,10 +783,11 @@ async def main():
             loop.close()
         """
         check_bucket_name(bucket_name)
-        response = await self._execute(
-            "GET", bucket_name, query_params={"policy": ""},
-        )
-        return await response.text()
+        async with aiohttp.ClientSession() as session:
+            response = await self._execute(
+                "GET", bucket_name, query_params={"policy": ""}, session=session
+            )
+            return await response.text()
 
     async def delete_bucket_policy(self, bucket_name):
         """
@@ -888,10 +929,11 @@ async def main():
             loop.close()
         """
         check_bucket_name(bucket_name)
-        response = await self._execute(
-            "GET", bucket_name, query_params={"notification": ""},
-        )
-        return unmarshal(NotificationConfig, await response.text())
+        async with aiohttp.ClientSession() as session:
+            response = await self._execute(
+                "GET", bucket_name, query_params={"notification": ""}, session=session
+            )
+            return unmarshal(NotificationConfig, await response.text())
 
     async def set_bucket_notification(self, bucket_name, config):
         """
@@ -1038,12 +1080,11 @@ async def main():
         """
         check_bucket_name(bucket_name)
         try:
-            response = await self._execute(
-                "GET",
-                bucket_name,
-                query_params={"encryption": ""},
-            )
-            return unmarshal(SSEConfig, await response.text())
+            async with aiohttp.ClientSession() as session:
+                response = await self._execute(
+                    "GET", bucket_name, query_params={"encryption": ""}, session=session
+                )
+                return unmarshal(SSEConfig, await response.text())
         except S3Error as exc:
             if exc.code != "ServerSideEncryptionConfigurationNotFoundError":
                 raise
@@ -1085,10 +1126,11 @@ async def main():
                 raise
 
     async def listen_bucket_notification(
-        self, bucket_name, prefix='', suffix='',
-        events=('s3:ObjectCreated:*',
-                's3:ObjectRemoved:*',
-                's3:ObjectAccessed:*')
+        self,
+        bucket_name,
+        prefix="",
+        suffix="",
+        events=("s3:ObjectCreated:*", "s3:ObjectRemoved:*", "s3:ObjectAccessed:*"),
     ):
         """
         Listen events of object prefix and suffix of a bucket. Caller should
@@ -1209,20 +1251,27 @@ async def main():
             loop.close()
         """
         check_bucket_name(bucket_name)
-        response = await self._execute(
-            "GET",
-            bucket_name,
-            query_params={"versioning": ""},
-        )
-        return unmarshal(VersioningConfig, await response.text())
+        async with aiohttp.ClientSession() as session:
+            response = await self._execute(
+                "GET", bucket_name, query_params={"versioning": ""}, session=session
+            )
+            return unmarshal(VersioningConfig, await response.text())
 
     # FIXME: Broken, do not use this function
     async def fput_object(
-        self, bucket_name, object_name, file_path,
+        self,
+        bucket_name,
+        object_name,
+        file_path,
         content_type="application/octet-stream",
-        metadata=None, sse=None, progress=False,
-        part_size=0, num_parallel_uploads=3,
-        tags=None, retention=None, legal_hold=False
+        metadata=None,
+        sse=None,
+        progress=False,
+        part_size=0,
+        num_parallel_uploads=3,
+        tags=None,
+        retention=None,
+        legal_hold=False,
     ):
         """
         Uploads data from a file to an object in a bucket.
@@ -1328,17 +1377,31 @@ async def main():
         file_size = os.stat(file_path).st_size
         with open(file_path, "rb") as file_data:
             return await self.put_object(
-                bucket_name, object_name, file_data, file_size,
+                bucket_name,
+                object_name,
+                file_data,
+                file_size,
                 content_type=content_type,
-                metadata=metadata, sse=sse, progress=progress,
-                part_size=part_size, num_parallel_uploads=num_parallel_uploads,
-                tags=tags, retention=retention, legal_hold=legal_hold,
+                metadata=metadata,
+                sse=sse,
+                progress=progress,
+                part_size=part_size,
+                num_parallel_uploads=num_parallel_uploads,
+                tags=tags,
+                retention=retention,
+                legal_hold=legal_hold,
             )
 
     async def fget_object(
-        self, bucket_name, object_name, file_path,
-        request_headers=None, ssec=None, version_id=None,
-        extra_query_params=None, tmp_file_path=None
+        self,
+        bucket_name,
+        object_name,
+        file_path,
+        request_headers=None,
+        ssec=None,
+        version_id=None,
+        extra_query_params=None,
+        tmp_file_path=None,
     ):
         """
         Downloads data of an object to file.
@@ -1407,9 +1470,7 @@ async def main():
         )
 
         # Write to a temporary file "file_path.part.minio" before saving.
-        tmp_file_path = (
-                tmp_file_path or file_path + "." + stat.etag + ".part.minio"
-        )
+        tmp_file_path = tmp_file_path or file_path + "." + stat.etag + ".part.minio"
         try:
             tmp_file_stat = os.stat(tmp_file_path)
         except IOError:
@@ -1421,29 +1482,38 @@ async def main():
 
         response = None
         try:
-            response = await self.get_object(
-                bucket_name,
-                object_name,
-                offset=offset,
-                request_headers=request_headers,
-                ssec=ssec,
-                version_id=version_id,
-                extra_query_params=extra_query_params,
-            )
-            async with aiofile.async_open(tmp_file_path, "wb") as tmp_file:
-                async for data in response.content.iter_chunked(n=1024 * 1024):
-                    await tmp_file.write(data)
-            if os.path.exists(file_path):
-                os.remove(file_path)  # For windows compatibility.
-            os.rename(tmp_file_path, file_path)
-            return stat
+            async with aiohttp.ClientSession() as session:
+                response = await self.get_object(
+                    bucket_name,
+                    object_name,
+                    offset=offset,
+                    request_headers=request_headers,
+                    ssec=ssec,
+                    version_id=version_id,
+                    extra_query_params=extra_query_params,
+                    session=session,
+                )
+                async with aiofile.async_open(tmp_file_path, "wb") as tmp_file:
+                    async for data in response.content.iter_chunked(n=1024 * 1024):
+                        await tmp_file.write(data)
+                if os.path.exists(file_path):
+                    os.remove(file_path)  # For windows compatibility.
+                os.rename(tmp_file_path, file_path)
+                return stat
         finally:
             pass
 
     async def get_object(
-        self, bucket_name, object_name, offset=0, length=0,
-        request_headers=None, ssec=None, version_id=None,
-        extra_query_params=None
+        self,
+        bucket_name,
+        object_name,
+        offset=0,
+        length=0,
+        request_headers=None,
+        ssec=None,
+        version_id=None,
+        extra_query_params=None,
+        session=None,
     ):
         """
         Get data of an object. Returned response should be closed after use to
@@ -1519,7 +1589,7 @@ async def main():
         headers.update(request_headers or {})
 
         if offset or length:
-            headers['Range'] = 'bytes={}-{}'.format(
+            headers["Range"] = "bytes={}-{}".format(
                 offset, offset + length - 1 if length else ""
             )
 
@@ -1533,13 +1603,21 @@ async def main():
             object_name,
             headers=headers,
             query_params=extra_query_params,
+            session=session,
         )
 
     async def copy_object(
-        self, bucket_name, object_name, source,
-        sse=None, metadata=None, tags=None, retention=None,
-        legal_hold=False, metadata_directive=None,
-        tagging_directive=None
+        self,
+        bucket_name,
+        object_name,
+        source,
+        sse=None,
+        metadata=None,
+        tags=None,
+        retention=None,
+        legal_hold=False,
+        metadata_directive=None,
+        tagging_directive=None,
     ):
         """
         Create an object by server-side copying data from another object.
@@ -1622,17 +1700,11 @@ async def main():
             raise ValueError("tags must be Tags type")
         if retention is not None and not isinstance(retention, Retention):
             raise ValueError("retention must be Retention type")
-        if (
-                metadata_directive is not None and
-                metadata_directive not in [COPY, REPLACE]
-        ):
+        if metadata_directive is not None and metadata_directive not in [COPY, REPLACE]:
             raise ValueError(
                 "metadata directive must be {0} or {1}".format(COPY, REPLACE),
             )
-        if (
-                tagging_directive is not None and
-                tagging_directive not in [COPY, REPLACE]
-        ):
+        if tagging_directive is not None and tagging_directive not in [COPY, REPLACE]:
             raise ValueError(
                 "tagging directive must be {0} or {1}".format(COPY, REPLACE),
             )
@@ -1648,9 +1720,9 @@ async def main():
             size = stat.size
 
         if (
-                source.offset is not None or
-                source.length is not None or
-                size > MAX_PART_SIZE
+            source.offset is not None
+            or source.length is not None
+            or size > MAX_PART_SIZE
         ):
             if metadata_directive == COPY:
                 raise ValueError(
@@ -1663,8 +1735,13 @@ async def main():
                     "object size greater than 5 GiB"
                 )
             return await self.compose_object(
-                bucket_name, object_name, ComposeSource.of(source),
-                sse=sse, metadata=metadata, tags=tags, retention=retention,
+                bucket_name,
+                object_name,
+                ComposeSource.of(source),
+                sse=sse,
+                metadata=metadata,
+                tags=tags,
+                retention=retention,
                 legal_hold=legal_hold,
             )
 
@@ -1674,21 +1751,23 @@ async def main():
         if tagging_directive:
             headers["x-amz-tagging-directive"] = tagging_directive
         headers.update(source.gen_copy_headers())
-        response = await self._execute(
-            "PUT",
-            bucket_name,
-            object_name=object_name,
-            headers=headers,
-        )
-        etag, last_modified = parse_copy_object(await response.text())
-        return ObjectWriteResult(
-            bucket_name,
-            object_name,
-            response.headers.get("x-amz-version-id"),
-            etag,
-            response.headers,
-            last_modified=last_modified,
-        )
+        async with aiohttp.ClientSession() as session:
+            response = await self._execute(
+                "PUT",
+                bucket_name,
+                object_name=object_name,
+                headers=headers,
+                session=session,
+            )
+            etag, last_modified = parse_copy_object(await response.text())
+            return ObjectWriteResult(
+                bucket_name,
+                object_name,
+                response.headers.get("x-amz-version-id"),
+                etag,
+                response.headers,
+                last_modified=last_modified,
+            )
 
     async def _calc_part_count(self, sources):
         """Calculate part count."""
@@ -1710,14 +1789,13 @@ async def _calc_part_count(self, sources):
             elif src.offset is not None:
                 size -= src.offset
 
-            if (
-                    size < MIN_PART_SIZE and
-                    len(sources) != 1 and
-                    i != len(sources)
-            ):
+            if size < MIN_PART_SIZE and len(sources) != 1 and i != len(sources):
                 raise ValueError(
                     "source {0}/{1}: size {2} must be greater than {3}".format(
-                        src.bucket_name, src.object_name, size, MIN_PART_SIZE,
+                        src.bucket_name,
+                        src.object_name,
+                        size,
+                        MIN_PART_SIZE,
                     ),
                 )
 
@@ -1737,16 +1815,18 @@ async def _calc_part_count(self, sources):
                 else:
                     last_part_size = MAX_PART_SIZE
                 if (
-                        last_part_size < MIN_PART_SIZE and
-                        len(sources) != 1 and
-                        i != len(sources)
+                    last_part_size < MIN_PART_SIZE
+                    and len(sources) != 1
+                    and i != len(sources)
                 ):
                     raise ValueError(
                         (
                             "source {0}/{1}: for multipart split upload of "
                             "{2}, last part size is less than {3}"
                         ).format(
-                            src.bucket_name, src.object_name, size,
+                            src.bucket_name,
+                            src.object_name,
+                            size,
                             MIN_PART_SIZE,
                         ),
                     )
@@ -1757,33 +1837,39 @@ async def _calc_part_count(self, sources):
         if part_count > MAX_MULTIPART_COUNT:
             raise ValueError(
                 (
-                    "Compose sources create more than allowed multipart "
-                    "count {0}"
+                    "Compose sources create more than allowed multipart " "count {0}"
                 ).format(MAX_MULTIPART_COUNT),
             )
         return part_count
 
     async def _upload_part_copy(
-        self, bucket_name, object_name, upload_id,
-        part_number, headers
+        self, bucket_name, object_name, upload_id, part_number, headers
     ):
         """Execute UploadPartCopy S3 API."""
         query_params = {
             "partNumber": str(part_number),
             "uploadId": upload_id,
         }
-        response = await self._execute(
-            "PUT",
-            bucket_name,
-            object_name,
-            headers=headers,
-            query_params=query_params,
-        )
-        return parse_copy_object(await response.text())
+        async with aiohttp.ClientSession() as session:
+            response = await self._execute(
+                "PUT",
+                bucket_name,
+                object_name,
+                headers=headers,
+                query_params=query_params,
+                session=session,
+            )
+            return parse_copy_object(await response.text())
 
     async def compose_object(  # pylint: disable=too-many-branches
-        self, bucket_name, object_name, sources,
-        sse=None, metadata=None, tags=None, retention=None,
+        self,
+        bucket_name,
+        object_name,
+        sources,
+        sse=None,
+        metadata=None,
+        tags=None,
+        retention=None,
         legal_hold=False,
     ):
         """
@@ -1873,14 +1959,15 @@ async def main():
             raise ValueError("retention must be Retention type")
 
         part_count = await self._calc_part_count(sources)
-        if (
-                part_count == 1 and
-                sources[0].offset is None and
-                sources[0].length is None
-        ):
+        if part_count == 1 and sources[0].offset is None and sources[0].length is None:
             return await self.copy_object(
-                bucket_name, object_name, CopySource.of(sources[0]),
-                sse=sse, metadata=metadata, tags=tags, retention=retention,
+                bucket_name,
+                object_name,
+                CopySource.of(sources[0]),
+                sse=sse,
+                metadata=metadata,
+                tags=tags,
+                retention=retention,
                 legal_hold=legal_hold,
                 metadata_directive=REPLACE if metadata else None,
                 tagging_directive=REPLACE if tags else None,
@@ -1888,7 +1975,9 @@ async def main():
 
         headers = genheaders(metadata, sse, tags, retention, legal_hold)
         upload_id = await self._create_multipart_upload(
-            bucket_name, object_name, headers,
+            bucket_name,
+            object_name,
+            headers,
         )
         ssec_headers = sse.headers() if isinstance(sse, SseCustomerKey) else {}
         try:
@@ -1906,15 +1995,12 @@ async def main():
                 if size <= MAX_PART_SIZE:
                     part_number += 1
                     if src.length is not None:
-                        headers["x-amz-copy-source-range"] = (
-                            "bytes={0}-{1}".format(
-                                offset,
-                                offset + src.length - 1
-                            )
+                        headers["x-amz-copy-source-range"] = "bytes={0}-{1}".format(
+                            offset, offset + src.length - 1
                         )
                     elif src.offset is not None:
-                        headers["x-amz-copy-source-range"] = (
-                            "bytes={0}-{1}".format(offset, offset + size - 1)
+                        headers["x-amz-copy-source-range"] = "bytes={0}-{1}".format(
+                            offset, offset + size - 1
                         )
                     etag, _ = await self._upload_part_copy(
                         bucket_name,
@@ -1932,8 +2018,8 @@ async def main():
                     if size < MAX_PART_SIZE:
                         end_bytes = start_bytes + size
                     headers_copy = headers.copy()
-                    headers_copy["x-amz-copy-source-range"] = (
-                        "bytes={0}-{1}".format(start_bytes, end_bytes)
+                    headers_copy["x-amz-copy-source-range"] = "bytes={0}-{1}".format(
+                        start_bytes, end_bytes
                     )
                     etag, _ = await self._upload_part_copy(
                         bucket_name,
@@ -1946,7 +2032,10 @@ async def main():
                     offset = start_bytes
                     size -= end_bytes - start_bytes
             result = await self._complete_multipart_upload(
-                bucket_name, object_name, upload_id, total_parts,
+                bucket_name,
+                object_name,
+                upload_id,
+                total_parts,
             )
             return ObjectWriteResult(
                 result.bucket_name,
@@ -1959,30 +2048,23 @@ async def main():
         except Exception as exc:
             if upload_id:
                 await self._abort_multipart_upload(
-                    bucket_name, object_name, upload_id,
+                    bucket_name,
+                    object_name,
+                    upload_id,
                 )
             raise exc
 
-    async def _abort_multipart_upload(
-        self,
-        bucket_name,
-        object_name,
-        upload_id
-    ):
+    async def _abort_multipart_upload(self, bucket_name, object_name, upload_id):
         """Execute AbortMultipartUpload S3 API."""
         await self._execute(
             "DELETE",
             bucket_name,
             object_name,
-            query_params={'uploadId': upload_id},
+            query_params={"uploadId": upload_id},
         )
 
     async def _complete_multipart_upload(
-        self,
-        bucket_name,
-        object_name,
-        upload_id,
-        parts
+        self, bucket_name, object_name, upload_id, parts
     ) -> CompleteMultipartUploadResult:
         """Execute CompleteMultipartUpload S3 API."""
         element = Element("CompleteMultipartUpload")
@@ -1991,59 +2073,70 @@ async def _complete_multipart_upload(
             SubElement(tag, "PartNumber", str(part.part_number))
             SubElement(tag, "ETag", '"' + part.etag + '"')
         body = getbytes(element)
-        response = await self._execute(
-            "POST",
-            bucket_name,
-            object_name,
-            body=body,
-            headers={
-                "Content-Type": 'application/xml',
-                "Content-MD5": md5sum_hash(body),
-            },
-            query_params={'uploadId': upload_id},
-        )
-        return await CompleteMultipartUploadResult.from_async_response(response)
+        async with aiohttp.ClientSession() as session:
+            response = await self._execute(
+                "POST",
+                bucket_name,
+                object_name,
+                body=body,
+                headers={
+                    "Content-Type": "application/xml",
+                    "Content-MD5": md5sum_hash(body),
+                },
+                query_params={"uploadId": upload_id},
+                session=session,
+            )
+            return await CompleteMultipartUploadResult.from_async_response(response)
 
     async def _create_multipart_upload(self, bucket_name, object_name, headers):
         """Execute CreateMultipartUpload S3 API."""
         if not headers.get("Content-Type"):
             headers["Content-Type"] = "application/octet-stream"
-        response = await self._execute(
-            "POST",
-            bucket_name,
-            object_name,
-            headers=headers,
-            query_params={"uploads": ""},
-        )
-        element = ET.fromstring(await response.text())
+        async with aiohttp.ClientSession() as session:
+            response = await self._execute(
+                "POST",
+                bucket_name,
+                object_name,
+                headers=headers,
+                query_params={"uploads": ""},
+                session=session,
+            )
+            element = ET.fromstring(await response.text())
         return findtext(element, "UploadId")
 
     async def _put_object(
-        self, bucket_name, object_name, data, headers,
-        query_params=None, progress=None
+        self, bucket_name, object_name, data, headers, query_params=None, progress=None
     ):
         """Execute PutObject S3 API."""
-        response = await self._execute(
-            "PUT",
-            bucket_name,
-            object_name,
-            body=data,
-            headers=headers,
-            query_params=query_params
-        )
-        if progress:
-            progress.update(len(data))
-        return ObjectWriteResult(
-            bucket_name,
-            object_name,
-            response.headers.get("x-amz-version-id"),
-            response.headers.get("etag").replace('"', ""),
-            response.headers,
-        )
+        async with aiohttp.ClientSession() as session:
+            response = await self._execute(
+                "PUT",
+                bucket_name,
+                object_name,
+                body=data,
+                headers=headers,
+                query_params=query_params,
+                session=session,
+            )
+            if progress:
+                progress.update(len(data))
+            return ObjectWriteResult(
+                bucket_name,
+                object_name,
+                response.headers.get("x-amz-version-id"),
+                response.headers.get("etag").replace('"', ""),
+                response.headers,
+            )
 
     async def _upload_part(
-        self, bucket_name, object_name, data, headers,
-        upload_id, part_number, progress=None
+        self,
+        bucket_name,
+        object_name,
+        data,
+        headers,
+        upload_id,
+        part_number,
+        progress=None,
     ):
         """Execute UploadPart S3 API."""
         query_params = {
@@ -2056,7 +2149,7 @@ async def _upload_part(
             data,
             headers,
             query_params=query_params,
-            progress=progress
+            progress=progress,
         )
         return result.etag
 
@@ -2065,11 +2158,20 @@ async def _upload_part_task(self, args, progress=None):
         return args[5], await self._upload_part(*args, progress=progress)
 
     async def put_object(
-        self, bucket_name, object_name, data, length,
+        self,
+        bucket_name,
+        object_name,
+        data,
+        length,
         content_type="application/octet-stream",
-        metadata=None, sse=None, progress=False,
-        part_size=0, num_parallel_uploads=3,
-        tags=None, retention=None, legal_hold=False
+        metadata=None,
+        sse=None,
+        progress=False,
+        part_size=0,
+        num_parallel_uploads=3,
+        tags=None,
+        retention=None,
+        legal_hold=False,
     ) -> ObjectWriteResult:
         """
         Uploads data from a stream to an object in a bucket.
@@ -2218,9 +2320,7 @@ async def main():
                     if part_number == part_count:
                         part_size = object_size - uploaded_size
                         stop = True
-                    part_data = await read_part_data(
-                        data, part_size
-                    )
+                    part_data = await read_part_data(data, part_size)
                     if len(part_data) != part_size:
                         raise IOError(
                             (
@@ -2229,9 +2329,7 @@ async def main():
                             ).format(part_size, len(part_data))
                         )
                 else:
-                    part_data = await read_part_data(
-                        data, part_size + 1, one_byte
-                    )
+                    part_data = await read_part_data(data, part_size + 1, one_byte)
                     # If part_data_size is less or equal to part_size,
                     # then we have reached last part.
                     if len(part_data) <= part_size:
@@ -2245,18 +2343,26 @@ async def main():
 
                 if part_count == 1:
                     return await self._put_object(
-                        bucket_name, object_name, part_data, headers,
+                        bucket_name,
+                        object_name,
+                        part_data,
+                        headers,
                     )
 
                 if not upload_id:
                     upload_id = await self._create_multipart_upload(
-                        bucket_name, object_name, headers,
+                        bucket_name,
+                        object_name,
+                        headers,
                     )
 
                 args = (
-                    bucket_name, object_name, part_data,
+                    bucket_name,
+                    object_name,
+                    part_data,
                     sse.headers() if isinstance(sse, SseCustomerKey) else None,
-                    upload_id, part_number,
+                    upload_id,
+                    part_number,
                 )
                 if num_parallel_uploads and num_parallel_uploads > 1:
                     parallel_tasks.append(
@@ -2265,12 +2371,16 @@ async def main():
                         )
                     )
                     if (
-                            part_number % num_parallel_uploads == 0
-                            or part_number == part_count
+                        part_number % num_parallel_uploads == 0
+                        or part_number == part_count
                     ):
                         parts.extend(
-                            (Part(number, etag) for number, etag in
-                             await asyncio.gather(*parallel_tasks))
+                            (
+                                Part(number, etag)
+                                for number, etag in await asyncio.gather(
+                                    *parallel_tasks
+                                )
+                            )
                         )
                         parallel_tasks.clear()
 
@@ -2279,7 +2389,10 @@ async def main():
                     parts.append(Part(part_number, etag))
 
             result = await self._complete_multipart_upload(
-                bucket_name, object_name, upload_id, parts,
+                bucket_name,
+                object_name,
+                upload_id,
+                parts,
             )
             return ObjectWriteResult(
                 result.bucket_name,
@@ -2292,15 +2405,22 @@ async def main():
         except Exception as exc:
             if upload_id:
                 await self._abort_multipart_upload(
-                    bucket_name, object_name, upload_id,
+                    bucket_name,
+                    object_name,
+                    upload_id,
                 )
             raise exc
 
     async def list_objects(
-        self, bucket_name, prefix=None, recursive=False,
-        start_after=None, include_user_meta=False,
-        include_version=False, use_api_v1=False,
-        use_url_encoding_type=True
+        self,
+        bucket_name,
+        prefix=None,
+        recursive=False,
+        start_after=None,
+        include_user_meta=False,
+        include_version=False,
+        use_api_v1=False,
+        use_url_encoding_type=True,
     ):
         """
         Lists object information of a bucket.
@@ -2384,8 +2504,12 @@ async def main():
         )
 
     async def stat_object(
-        self, bucket_name, object_name, ssec=None, version_id=None,
-        extra_query_params=None
+        self,
+        bucket_name,
+        object_name,
+        ssec=None,
+        version_id=None,
+        extra_query_params=None,
     ):
         """
         Get object information and metadata of an object.
@@ -2455,36 +2579,37 @@ async def main():
         headers = ssec.headers() if ssec else {}
         query_params = extra_query_params or {}
         query_params.update({"versionId": version_id} if version_id else {})
-        response = await self._execute(
-            "HEAD",
-            bucket_name,
-            object_name,
-            headers=headers,
-            query_params=query_params,
-        )
+        async with aiohttp.ClientSession() as session:
+            response = await self._execute(
+                "HEAD",
+                bucket_name,
+                object_name,
+                headers=headers,
+                query_params=query_params,
+                session=session,
+            )
 
-        last_modified = response.headers.get("last-modified")
-        if last_modified:
-            last_modified = time.from_http_header(last_modified)
+            last_modified = response.headers.get("last-modified")
+            if last_modified:
+                last_modified = time.from_http_header(last_modified)
 
-        return Object(
-            bucket_name,
-            object_name,
-            last_modified=last_modified,
-            etag=response.headers.get("etag", "").replace('"', ""),
-            size=int(response.headers.get("content-length", "0")),
-            content_type=response.headers.get("content-type"),
-            metadata=response.headers,
-            version_id=response.headers.get("x-amz-version-id"),
-        )
+            return Object(
+                bucket_name,
+                object_name,
+                last_modified=last_modified,
+                etag=response.headers.get("etag", "").replace('"', ""),
+                size=int(response.headers.get("content-length", "0")),
+                content_type=response.headers.get("content-type"),
+                metadata=response.headers,
+                version_id=response.headers.get("x-amz-version-id"),
+            )
 
     async def list_object_versions(self, bucket_name):
-        response = await self._execute(
-            "GET",
-            bucket_name,
-            query_params={"versions": ""}
-        )
-        return await response.text()
+        async with aiohttp.ClientSession() as session:
+            response = await self._execute(
+                "GET", bucket_name, query_params={"versions": ""}, session=session
+            )
+            return await response.text()
 
     async def remove_object(self, bucket_name, object_name, version_id=None):
         """
@@ -2531,8 +2656,7 @@ async def main():
         )
 
     async def _delete_objects(
-        self, bucket_name, delete_object_list,
-        quiet=False, bypass_governance_mode=False
+        self, bucket_name, delete_object_list, quiet=False, bypass_governance_mode=False
     ):
         """
         Delete multiple objects.
@@ -2548,25 +2672,26 @@ async def _delete_objects(
         headers = {"Content-MD5": md5sum_hash(body)}
         if bypass_governance_mode:
             headers["x-amz-bypass-governance-retention"] = "true"
-        response = await self._execute(
-            "POST",
-            bucket_name,
-            body=body,
-            headers=headers,
-            query_params={"delete": ""},
-        )
+        async with aiohttp.ClientSession() as session:
+            response = await self._execute(
+                "POST",
+                bucket_name,
+                body=body,
+                headers=headers,
+                query_params={"delete": ""},
+                session=session,
+            )
 
-        element = ET.fromstring(await response.text())
-        return (
-            DeleteResult([], [DeleteError.fromxml(element)])
-            if element.tag.endswith("Error")
-            else unmarshal(DeleteResult, await response.text())
-        )
+            element = ET.fromstring(await response.text())
+            return (
+                DeleteResult([], [DeleteError.fromxml(element)])
+                if element.tag.endswith("Error")
+                else unmarshal(DeleteResult, await response.text())
+            )
 
     # TODO Return asynchronous iterator for objects
     async def remove_objects(
-        self, bucket_name, delete_object_list,
-        bypass_governance_mode=False
+        self, bucket_name, delete_object_list, bypass_governance_mode=False
     ):
         """
         Remove multiple objects.
@@ -2631,8 +2756,10 @@ async def main():
         while True:
             # get 1000 entries or whatever available.
             objects = [
-                delete_object for _, delete_object in zip(
-                    range(1000), delete_object_list,
+                delete_object
+                for _, delete_object in zip(
+                    range(1000),
+                    delete_object_list,
                 )
             ]
 
@@ -2647,17 +2774,20 @@ async def main():
             )
 
             return tuple(
-                filter(
-                    lambda error: error.code != "NoSuchVersion",
-                    result.error_list
-                )
+                filter(lambda error: error.code != "NoSuchVersion", result.error_list)
             )
 
     async def get_presigned_url(
-        self, method, bucket_name, object_name,
-        expires=timedelta(days=7), response_headers=None,
-        request_date=None, version_id=None,
-        extra_query_params=None, change_host=None
+        self,
+        method,
+        bucket_name,
+        object_name,
+        expires=timedelta(days=7),
+        response_headers=None,
+        request_date=None,
+        version_id=None,
+        extra_query_params=None,
+        change_host=None,
     ):
         """
         Get presigned URL of an object for HTTP method, expiry time and custom
@@ -2801,13 +2931,15 @@ async def main():
         return urlunsplit(url)
 
     async def presigned_get_object(
-        self, bucket_name, object_name,
+        self,
+        bucket_name,
+        object_name,
         expires=timedelta(days=7),
         response_headers=None,
         request_date=None,
         version_id=None,
         extra_query_params=None,
-        change_host=None
+        change_host=None,
     ):
         """
         Get presigned URL of an object to download its data with expiry time
@@ -2891,12 +3023,11 @@ async def main():
             request_date=request_date,
             version_id=version_id,
             extra_query_params=extra_query_params,
-            change_host=change_host
+            change_host=change_host,
         )
 
     async def presigned_put_object(
-        self, bucket_name, object_name,
-        expires=timedelta(days=7), change_host=None
+        self, bucket_name, object_name, expires=timedelta(days=7), change_host=None
     ):
         """
         Get presigned URL of an object to upload data with expiry time and
@@ -3044,11 +3175,7 @@ async def main():
             loop.close()
         """
         check_bucket_name(bucket_name)
-        await self._execute(
-            "DELETE",
-            bucket_name,
-            query_params={"replication": ""}
-        )
+        await self._execute("DELETE", bucket_name, query_params={"replication": ""})
 
     async def get_bucket_replication(self, bucket_name):
         """
@@ -3078,10 +3205,14 @@ async def main():
         """
         check_bucket_name(bucket_name)
         try:
-            response = await self._execute(
-                "GET", bucket_name, query_params={"replication": ""},
-            )
-            return unmarshal(ReplicationConfig, await response.text())
+            async with aiohttp.ClientSession() as session:
+                response = await self._execute(
+                    "GET",
+                    bucket_name,
+                    query_params={"replication": ""},
+                    session=session,
+                )
+                return unmarshal(ReplicationConfig, await response.text())
         except S3Error as exc:
             if exc.code != "ReplicationConfigurationNotFoundError":
                 raise
@@ -3096,10 +3227,8 @@ async def set_bucket_replication(self, bucket_name, config):
 
         Example::
             from miniopy_async import Minio
-            from miniopy_async.commonconfig import DISABLED, ENABLED,
-            AndOperator, Filter
-            from miniopy_async.replicationconfig import (
-            DeleteMarkerReplication, Destination, ReplicationConfig, Rule)
+            from miniopy_async.commonconfig import DISABLED, ENABLED, AndOperator, Filter, Tags
+            from miniopy_async.replicationconfig import (DeleteMarkerReplication, Destination, ReplicationConfig, Rule)
             import asyncio
 
             client = Minio(
@@ -3109,6 +3238,10 @@ async def set_bucket_replication(self, bucket_name, config):
                 secure=True  # http for False, https for True
             )
 
+            bucket_tags = Tags.new_bucket_tags()
+            bucket_tags["Project"] = "Project One"
+            bucket_tags["User"] = "jsmith"
+
             config = ReplicationConfig(
                 "REPLACE-WITH-ACTUAL-ROLE",
                 [
@@ -3123,7 +3256,7 @@ async def set_bucket_replication(self, bucket_name, config):
                         rule_filter=Filter(
                             AndOperator(
                                 "TaxDocs",
-                                {"key1": "value1", "key2": "value2"},
+                                bucket_tags,
                             ),
                         ),
                         rule_id="rule1",
@@ -3176,11 +3309,7 @@ async def main():
             loop.close()
         """
         check_bucket_name(bucket_name)
-        await self._execute(
-            "DELETE",
-            bucket_name,
-            query_params={"lifecycle": ""}
-        )
+        await self._execute("DELETE", bucket_name, query_params={"lifecycle": ""})
 
     async def get_bucket_lifecycle(self, bucket_name):
         """
@@ -3210,10 +3339,11 @@ async def main():
         """
         check_bucket_name(bucket_name)
         try:
-            response = await self._execute(
-                "GET", bucket_name, query_params={"lifecycle": ""},
-            )
-            return unmarshal(LifecycleConfig, await response.text())
+            async with aiohttp.ClientSession() as session:
+                response = await self._execute(
+                    "GET", bucket_name, query_params={"lifecycle": ""}, session=session
+                )
+                return unmarshal(LifecycleConfig, await response.text())
         except S3Error as exc:
             if exc.code != "NoSuchLifecycleConfiguration":
                 raise
@@ -3331,11 +3461,12 @@ async def main():
         """
         check_bucket_name(bucket_name)
         try:
-            response = await self._execute(
-                "GET", bucket_name, query_params={"tagging": ""},
-            )
-            tagging = unmarshal(Tagging, await response.text())
-            return tagging.tags
+            async with aiohttp.ClientSession() as session:
+                response = await self._execute(
+                    "GET", bucket_name, query_params={"tagging": ""}, session=session
+                )
+                tagging = unmarshal(Tagging, await response.text())
+                return tagging.tags
         except S3Error as exc:
             if exc.code != "NoSuchTagSet":
                 raise
@@ -3383,12 +3514,7 @@ async def main():
             query_params={"tagging": ""},
         )
 
-    async def delete_object_tags(
-        self,
-        bucket_name,
-        object_name,
-        version_id=None
-    ):
+    async def delete_object_tags(self, bucket_name, object_name, version_id=None):
         """
         Delete tags configuration of an object.
 
@@ -3458,26 +3584,22 @@ async def main():
         query_params = {"versionId": version_id} if version_id else {}
         query_params["tagging"] = ""
         try:
-            response = await self._execute(
-                "GET",
-                bucket_name,
-                object_name=object_name,
-                query_params=query_params,
-            )
-            tagging = unmarshal(Tagging, await response.text())
-            return tagging.tags
+            async with aiohttp.ClientSession() as session:
+                response = await self._execute(
+                    "GET",
+                    bucket_name,
+                    object_name=object_name,
+                    query_params=query_params,
+                    session=session,
+                )
+                tagging = unmarshal(Tagging, await response.text())
+                return tagging.tags
         except S3Error as exc:
             if exc.code != "NoSuchTagSet":
                 raise
         return None
 
-    async def set_object_tags(
-        self,
-        bucket_name,
-        object_name,
-        tags,
-        version_id=None
-    ):
+    async def set_object_tags(self, bucket_name, object_name, tags, version_id=None):
         """
         Set tags configuration to an object.
 
@@ -3526,7 +3648,10 @@ async def main():
         )
 
     async def enable_object_legal_hold(
-        self, bucket_name, object_name, version_id=None,
+        self,
+        bucket_name,
+        object_name,
+        version_id=None,
     ):
         """
         Enable legal hold on an object.
@@ -3568,7 +3693,10 @@ async def main():
         )
 
     async def disable_object_legal_hold(
-        self, bucket_name, object_name, version_id=None,
+        self,
+        bucket_name,
+        object_name,
+        version_id=None,
     ):
         """
         Disable legal hold on an object.
@@ -3610,7 +3738,10 @@ async def main():
         )
 
     async def is_object_legal_hold_enabled(
-        self, bucket_name, object_name, version_id=None,
+        self,
+        bucket_name,
+        object_name,
+        version_id=None,
     ):
         """
         Returns true if legal hold is enabled on an object.
@@ -3646,14 +3777,16 @@ async def main():
         query_params = {"versionId", version_id} if version_id else {}
         query_params["legal-hold"] = ""
         try:
-            response = await self._execute(
-                "GET",
-                bucket_name,
-                object_name=object_name,
-                query_params=query_params,
-            )
-            legal_hold = unmarshal(LegalHold, await response.text())
-            return legal_hold.status
+            async with aiohttp.ClientSession() as session:
+                response = await self._execute(
+                    "GET",
+                    bucket_name,
+                    object_name=object_name,
+                    query_params=query_params,
+                    session=session,
+                )
+                legal_hold = unmarshal(LegalHold, await response.text())
+                return legal_hold.status
         except S3Error as exc:
             if exc.code != "NoSuchObjectLockConfiguration":
                 raise
@@ -3714,10 +3847,11 @@ async def main():
             loop.close()
         """
         check_bucket_name(bucket_name)
-        response = await self._execute(
-            "GET", bucket_name, query_params={"object-lock": ""},
-        )
-        return unmarshal(ObjectLockConfig, await response.text())
+        async with aiohttp.ClientSession() as session:
+            response = await self._execute(
+                "GET", bucket_name, query_params={"object-lock": ""}, session=session
+            )
+            return unmarshal(ObjectLockConfig, await response.text())
 
     async def set_object_lock_config(self, bucket_name, config):
         """
@@ -3761,7 +3895,10 @@ async def main():
         )
 
     async def get_object_retention(
-        self, bucket_name, object_name, version_id=None,
+        self,
+        bucket_name,
+        object_name,
+        version_id=None,
     ):
         """
         Get retention configuration of an object.
@@ -3796,20 +3933,26 @@ async def main():
         query_params = {"versionId", version_id} if version_id else {}
         query_params["retention"] = ""
         try:
-            response = await self._execute(
-                "GET",
-                bucket_name,
-                object_name=object_name,
-                query_params=query_params,
-            )
-            return unmarshal(Retention, await response.text())
+            async with aiohttp.ClientSession() as session:
+                response = await self._execute(
+                    "GET",
+                    bucket_name,
+                    object_name=object_name,
+                    query_params=query_params,
+                    session=session,
+                )
+                return unmarshal(Retention, await response.text())
         except S3Error as exc:
             if exc.code != "NoSuchObjectLockConfiguration":
                 raise
         return None
 
     async def set_object_retention(
-        self, bucket_name, object_name, config, version_id=None,
+        self,
+        bucket_name,
+        object_name,
+        config,
+        version_id=None,
     ):
         """
         Set retention configuration on an object.
@@ -3928,15 +4071,17 @@ async def _list_objects(
             if version_id_marker:
                 query["version-id-marker"] = version_id_marker
 
-            response = await self._execute(
-                "GET",
-                bucket_name,
-                query_params=query
-            )
+            async with aiohttp.ClientSession() as session:
+                response = await self._execute(
+                    "GET", bucket_name, query_params=query, session=session
+                )
 
-            objects, is_truncated, start_after, version_id_marker = (
-                await parse_list_objects(response)
-            )
+                (
+                    objects,
+                    is_truncated,
+                    start_after,
+                    version_id_marker,
+                ) = await parse_list_objects(response)
 
             if not include_version:
                 version_id_marker = None
@@ -3946,11 +4091,16 @@ async def _list_objects(
             return objects
 
     async def _list_multipart_uploads(
-        self, bucket_name, delimiter=None,
-        encoding_type=None, key_marker=None,
-        max_uploads=None, prefix=None,
-        upload_id_marker=None, extra_headers=None,
-        extra_query_params=None
+        self,
+        bucket_name,
+        delimiter=None,
+        encoding_type=None,
+        key_marker=None,
+        max_uploads=None,
+        prefix=None,
+        upload_id_marker=None,
+        extra_headers=None,
+        extra_query_params=None,
     ):
         """
         Execute ListMultipartUploads S3 API.
@@ -3987,18 +4137,25 @@ async def _list_multipart_uploads(
         if upload_id_marker:
             query_params["upload-id-marker"] = upload_id_marker
 
-        response = await self._execute(
-            "GET",
-            bucket_name,
-            query_params=query_params,
-            headers=extra_headers,
-        )
-        return await ListMultipartUploadsResult.from_async_response(response)
+        async with aiohttp.ClientSession() as session:
+            response = await self._execute(
+                "GET",
+                bucket_name,
+                query_params=query_params,
+                headers=extra_headers,
+                session=session,
+            )
+            return await ListMultipartUploadsResult.from_async_response(response.text())
 
     async def _list_parts(
-        self, bucket_name, object_name, upload_id,
-        max_parts=None, part_number_marker=None,
-        extra_headers=None, extra_query_params=None
+        self,
+        bucket_name,
+        object_name,
+        upload_id,
+        max_parts=None,
+        part_number_marker=None,
+        extra_headers=None,
+        extra_query_params=None,
     ):
         """
         Execute ListParts S3 API.
@@ -4024,28 +4181,13 @@ async def _list_parts(
         if part_number_marker:
             query_params["part-number-marker"] = part_number_marker
 
-        response = await self._execute(
-            "GET",
-            bucket_name,
-            object_name=object_name,
-            query_params=query_params,
-            headers=extra_headers,
-        )
-        return await ListPartsResult.from_async_response(response)
-
-# def _attach_finalizer(
-#         res: aiohttp.ClientResponse,
-#         session: aiohttp.ClientSession,
-#         loop: asyncio.AbstractEventLoop):
-#     '''
-#     This attaches a finalizer to the response object.
-#     The finalizer holds a reference to the session, so that
-#     the finalizer must be done before the session can be GC-ed.
-#     '''
-#     weakref.finalize(
-#         res,
-#         # `session.close()` might be submitted to the eventLoop from a different
-#         # thread than the one running the eventLoop. Therefore, we need `run_coroutine_threadsafe`
-#         asyncio.run_coroutine_threadsafe,
-#         session.close(),
-#         loop)
+        async with aiohttp.ClientSession() as session:
+            response = await self._execute(
+                "GET",
+                bucket_name,
+                object_name=object_name,
+                query_params=query_params,
+                headers=extra_headers,
+                session=session,
+            )
+            return await ListPartsResult.from_async_response(response.text())
diff --git a/miniopy_async/commonconfig.py b/miniopy_async/commonconfig.py
index bfee697..018977c 100644
--- a/miniopy_async/commonconfig.py
+++ b/miniopy_async/commonconfig.py
@@ -155,10 +155,7 @@ def fromxml(cls, element):
         """Create new object with values from XML element."""
         element = find(element, "And")
         prefix = findtext(element, "Prefix")
-        tags = (
-            None if find(element, "Tag") is None
-            else Tags.fromxml(element)
-        )
+        tags = None if find(element, "Tag") is None else Tags.fromxml(element)
         return cls(prefix, tags)
 
     def toxml(self, element):
@@ -175,11 +172,7 @@ class Filter:
     """Lifecycle rule filter."""
 
     def __init__(self, and_operator=None, prefix=None, tag=None):
-        valid = (
-                (and_operator is not None) ^
-                (prefix is not None) ^
-                (tag is not None)
-        )
+        valid = (and_operator is not None) ^ (prefix is not None) ^ (tag is not None)
         if not valid:
             raise ValueError("only one of and, prefix or tag must be provided")
         self._and_operator = and_operator
@@ -206,8 +199,7 @@ def fromxml(cls, element):
         """Create new object with values from XML element."""
         element = find(element, "Filter")
         and_operator = (
-            None if find(element, "And") is None
-            else AndOperator.fromxml(element)
+            None if find(element, "And") is None else AndOperator.fromxml(element)
         )
         prefix = findtext(element, "Prefix")
         tag = None if find(element, "Tag") is None else Tag.fromxml(element)
@@ -227,6 +219,7 @@ def toxml(self, element):
 
 class BaseRule:
     """Base rule class for Replication and Lifecycle."""
+
     __metaclass__ = ABCMeta
 
     def __init__(self, rule_filter=None, rule_id=None):
@@ -253,9 +246,8 @@ def rule_id(self):
     def parsexml(element):
         """Parse XML and return filter and ID."""
         return (
-                   None if find(element, "Filter") is None
-                   else Filter.fromxml(element)
-               ), findtext(element, "ID")
+            None if find(element, "Filter") is None else Filter.fromxml(element)
+        ), findtext(element, "ID")
 
     def toxml(self, element):
         """Convert to XML."""
@@ -274,13 +266,22 @@ def check_status(status):
 
 class ObjectConditionalReadArgs:
     """Base argument class holds condition properties for reading object."""
+
     __metaclass__ = ABCMeta
 
     def __init__(
-        self, bucket_name, object_name, region=None, version_id=None,
-        ssec=None, offset=None, length=None, match_etag=None,
-        not_match_etag=None, modified_since=None,
-        unmodified_since=None
+        self,
+        bucket_name,
+        object_name,
+        region=None,
+        version_id=None,
+        ssec=None,
+        offset=None,
+        length=None,
+        match_etag=None,
+        not_match_etag=None,
+        modified_since=None,
+        unmodified_since=None,
     ):
         if ssec is not None and not isinstance(ssec, SseCustomerKey):
             raise ValueError("ssec must be SseCustomerKey type")
@@ -292,14 +293,12 @@ def __init__(
             raise ValueError("match_etag must not be empty")
         if not_match_etag is not None and not_match_etag == "":
             raise ValueError("not_match_etag must not be empty")
-        if (
-                modified_since is not None and
-                not isinstance(modified_since, datetime.datetime)
+        if modified_since is not None and not isinstance(
+            modified_since, datetime.datetime
         ):
             raise ValueError("modified_since must be datetime.datetime type")
-        if (
-                unmodified_since is not None and
-                not isinstance(unmodified_since, datetime.datetime)
+        if unmodified_since is not None and not isinstance(
+            unmodified_since, datetime.datetime
         ):
             raise ValueError("unmodified_since must be datetime.datetime type")
 
@@ -384,12 +383,12 @@ def gen_copy_headers(self):
         if self._not_match_etag:
             headers["x-amz-copy-source-if-none-match"] = self._not_match_etag
         if self._modified_since:
-            headers["x-amz-copy-source-if-modified-since"] = (
-                to_http_header(self._modified_since)
+            headers["x-amz-copy-source-if-modified-since"] = to_http_header(
+                self._modified_since
             )
         if self._unmodified_since:
-            headers["x-amz-copy-source-if-unmodified-since"] = (
-                to_http_header(self._unmodified_since)
+            headers["x-amz-copy-source-if-unmodified-since"] = to_http_header(
+                self._unmodified_since
             )
         return headers
 
@@ -401,9 +400,17 @@ class CopySource(ObjectConditionalReadArgs):
     def of(cls, src):
         """Create CopySource from another source."""
         return cls(
-            src.bucket_name, src.object_name, src.region, src.version_id,
-            src.ssec, src.offset, src.length, src.match_etag,
-            src.not_match_etag, src.modified_since, src.unmodified_since,
+            src.bucket_name,
+            src.object_name,
+            src.region,
+            src.version_id,
+            src.ssec,
+            src.offset,
+            src.length,
+            src.match_etag,
+            src.not_match_etag,
+            src.modified_since,
+            src.unmodified_since,
         )
 
 
@@ -411,14 +418,31 @@ class ComposeSource(ObjectConditionalReadArgs):
     """A source object defintion for compose_object method."""
 
     def __init__(
-        self, bucket_name, object_name, region=None, version_id=None,
-        ssec=None, offset=None, length=None, match_etag=None,
-        not_match_etag=None, modified_since=None,
-        unmodified_since=None
+        self,
+        bucket_name,
+        object_name,
+        region=None,
+        version_id=None,
+        ssec=None,
+        offset=None,
+        length=None,
+        match_etag=None,
+        not_match_etag=None,
+        modified_since=None,
+        unmodified_since=None,
     ):
         super().__init__(
-            bucket_name, object_name, region, version_id, ssec, offset, length,
-            match_etag, not_match_etag, modified_since, unmodified_since,
+            bucket_name,
+            object_name,
+            region,
+            version_id,
+            ssec,
+            offset,
+            length,
+            match_etag,
+            not_match_etag,
+            modified_since,
+            unmodified_since,
         )
         self._object_size = None
         self._headers = None
@@ -455,8 +479,7 @@ def object_size(self):
         """Get object size."""
         if self._object_size is None:
             raise MinioException(
-                "build_headers() must be called prior to "
-                "this method invocation",
+                "build_headers() must be called prior to " "this method invocation",
             )
         return self._object_size
 
@@ -465,8 +488,7 @@ def headers(self):
         """Get headers."""
         if self._headers is None:
             raise MinioException(
-                "build_headers() must be called prior to "
-                "this method invocation",
+                "build_headers() must be called prior to " "this method invocation",
             )
         return self._headers.copy()
 
@@ -474,7 +496,15 @@ def headers(self):
     def of(cls, src):
         """Create ComposeSource from another source."""
         return cls(
-            src.bucket_name, src.object_name, src.region, src.version_id,
-            src.ssec, src.offset, src.length, src.match_etag,
-            src.not_match_etag, src.modified_since, src.unmodified_since,
+            src.bucket_name,
+            src.object_name,
+            src.region,
+            src.version_id,
+            src.ssec,
+            src.offset,
+            src.length,
+            src.match_etag,
+            src.not_match_etag,
+            src.modified_since,
+            src.unmodified_since,
         )
diff --git a/miniopy_async/credentials/__init__.py b/miniopy_async/credentials/__init__.py
index 1ddfbea..fa5833d 100644
--- a/miniopy_async/credentials/__init__.py
+++ b/miniopy_async/credentials/__init__.py
@@ -24,8 +24,18 @@
 
 # pylint: disable=unused-import
 from .credentials import Credentials
-from .providers import (AssumeRoleProvider, AWSConfigProvider, ChainedProvider,
-                        ClientGrantsProvider, EnvAWSProvider, EnvMinioProvider,
-                        IamAwsProvider, LdapIdentityProvider,
-                        MinioClientConfigProvider, Provider, StaticProvider,
-                        WebIdentityProvider, CertificateIdentityProvider)
+from .providers import (
+    AssumeRoleProvider,
+    AWSConfigProvider,
+    ChainedProvider,
+    ClientGrantsProvider,
+    EnvAWSProvider,
+    EnvMinioProvider,
+    IamAwsProvider,
+    LdapIdentityProvider,
+    MinioClientConfigProvider,
+    Provider,
+    StaticProvider,
+    WebIdentityProvider,
+    CertificateIdentityProvider,
+)
diff --git a/miniopy_async/credentials/credentials.py b/miniopy_async/credentials/credentials.py
index f23315f..d1fc194 100644
--- a/miniopy_async/credentials/credentials.py
+++ b/miniopy_async/credentials/credentials.py
@@ -27,7 +27,11 @@ class Credentials:
     """
 
     def __init__(
-            self, access_key, secret_key, session_token=None, expiration=None,
+        self,
+        access_key,
+        secret_key,
+        session_token=None,
+        expiration=None,
     ):
         if not access_key:
             raise ValueError("Access key must not be empty")
@@ -39,9 +43,7 @@ def __init__(
         self._secret_key = secret_key
         self._session_token = session_token
         if expiration and expiration.tzinfo:
-            expiration = (
-                expiration.astimezone(timezone.utc).replace(tzinfo=None)
-            )
+            expiration = expiration.astimezone(timezone.utc).replace(tzinfo=None)
         self._expiration = expiration
 
     @property
@@ -63,5 +65,6 @@ def is_expired(self):
         """Check whether this credentials expired or not."""
         return (
             self._expiration < (datetime.utcnow() + timedelta(seconds=10))
-            if self._expiration else False
+            if self._expiration
+            else False
         )
diff --git a/miniopy_async/credentials/providers.py b/miniopy_async/credentials/providers.py
index b3efc37..1d8ac84 100644
--- a/miniopy_async/credentials/providers.py
+++ b/miniopy_async/credentials/providers.py
@@ -74,15 +74,12 @@ def _urlopen(http_client, method, url, body=None, headers=None):
 
 def _user_home_dir():
     """Return current user home folder."""
-    return (
-        os.environ.get("HOME") or
-        os.environ.get("UserProfile") or
-        str(Path.home())
-    )
+    return os.environ.get("HOME") or os.environ.get("UserProfile") or str(Path.home())
 
 
 class Provider:  # pylint: disable=too-few-public-methods
     """Credential retriever."""
+
     __metaclass__ = ABCMeta
 
     @abstractmethod
@@ -94,9 +91,17 @@ class AssumeRoleProvider(Provider):
     """Assume-role credential provider."""
 
     def __init__(
-            self, sts_endpoint, access_key, secret_key, duration_seconds=0,
-            policy=None, region=None, role_arn=None, role_session_name=None,
-            external_id=None, http_client=None,
+        self,
+        sts_endpoint,
+        access_key,
+        secret_key,
+        duration_seconds=0,
+        policy=None,
+        region=None,
+        role_arn=None,
+        role_session_name=None,
+        external_id=None,
+        http_client=None,
     ):
         self._sts_endpoint = sts_endpoint
         self._access_key = access_key
@@ -134,9 +139,8 @@ def __init__(
         url = urlsplit(sts_endpoint)
         self._url = url
         self._host = url.netloc
-        if (
-                (url.scheme == "http" and url.port == 80) or
-                (url.scheme == "https" and url.port == 443)
+        if (url.scheme == "http" and url.port == 80) or (
+            url.scheme == "https" and url.port == 443
         ):
             self._host = url.hostname
         self._credentials = None
@@ -170,7 +174,8 @@ def retrieve(self):
         )
 
         self._credentials = _parse_credentials(
-            res.data.decode(), "AssumeRoleResult",
+            res.data.decode(),
+            "AssumeRoleResult",
         )
 
         return self._credentials
@@ -216,12 +221,11 @@ def retrieve(self):
         """Retrieve credentials."""
         return Credentials(
             access_key=(
-                os.environ.get("AWS_ACCESS_KEY_ID") or
-                os.environ.get("AWS_ACCESS_KEY")
+                os.environ.get("AWS_ACCESS_KEY_ID") or os.environ.get("AWS_ACCESS_KEY")
             ),
             secret_key=(
-                os.environ.get("AWS_SECRET_ACCESS_KEY") or
-                os.environ.get("AWS_SECRET_KEY")
+                os.environ.get("AWS_SECRET_ACCESS_KEY")
+                or os.environ.get("AWS_SECRET_KEY")
             ),
             session_token=os.environ.get("AWS_SESSION_TOKEN"),
         )
@@ -243,9 +247,9 @@ class AWSConfigProvider(Provider):
 
     def __init__(self, filename=None, profile=None):
         self._filename = (
-            filename or
-            os.environ.get("AWS_SHARED_CREDENTIALS_FILE") or
-            os.path.join(_user_home_dir(), ".aws", "credentials")
+            filename
+            or os.environ.get("AWS_SHARED_CREDENTIALS_FILE")
+            or os.path.join(_user_home_dir(), ".aws", "credentials")
         )
         self._profile = profile or os.environ.get("AWS_PROFILE") or "default"
 
@@ -292,13 +296,10 @@ class MinioClientConfigProvider(Provider):
     """Credential provider from MinIO Client configuration file."""
 
     def __init__(self, filename=None, alias=None):
-        self._filename = (
-            filename or
-            os.path.join(
-                _user_home_dir(),
-                "mc" if sys.platform == "win32" else ".mc",
-                "config.json",
-            )
+        self._filename = filename or os.path.join(
+            _user_home_dir(),
+            "mc" if sys.platform == "win32" else ".mc",
+            "config.json",
         )
         self._alias = alias or os.environ.get("MINIO_ALIAS") or "s3"
 
@@ -338,7 +339,7 @@ def _check_loopback_host(url):
 
 
 def _get_jwt_token(token_file):
-    """Read and return content of token file. """
+    """Read and return content of token file."""
     try:
         with open(token_file, encoding="utf-8") as file:
             return {"access_token": file.read(), "expires_in": "0"}
@@ -371,7 +372,7 @@ def __init__(self, custom_endpoint=None, http_client=None):
         self._credentials = None
 
     def fetch(self, url):
-        """Fetch credentials from EC2/ECS. """
+        """Fetch credentials from EC2/ECS."""
 
         res = _urlopen(self._http_client, "GET", url)
         data = json.loads(res.data)
@@ -422,8 +423,8 @@ def retrieve(self):
         else:
             if not url:
                 url = (
-                    "http://169.254.169.254" +
-                    "/latest/meta-data/iam/security-credentials/"
+                    "http://169.254.169.254"
+                    + "/latest/meta-data/iam/security-credentials/"
                 )
 
             res = _urlopen(self._http_client, "GET", url)
@@ -440,15 +441,23 @@ class LdapIdentityProvider(Provider):
     """Credential provider using AssumeRoleWithLDAPIdentity API."""
 
     def __init__(
-            self, sts_endpoint, ldap_username, ldap_password, http_client=None,
+        self,
+        sts_endpoint,
+        ldap_username,
+        ldap_password,
+        http_client=None,
     ):
-        self._sts_endpoint = sts_endpoint + "?" + urlencode(
-            {
-                "Action": "AssumeRoleWithLDAPIdentity",
-                "Version": "2011-06-15",
-                "LDAPUsername": ldap_username,
-                "LDAPPassword": ldap_password,
-            },
+        self._sts_endpoint = (
+            sts_endpoint
+            + "?"
+            + urlencode(
+                {
+                    "Action": "AssumeRoleWithLDAPIdentity",
+                    "Version": "2011-06-15",
+                    "LDAPUsername": ldap_username,
+                    "LDAPPassword": ldap_password,
+                },
+            )
         )
         self._http_client = http_client or urllib3.PoolManager(
             retries=urllib3.Retry(
@@ -472,7 +481,8 @@ def retrieve(self):
         )
 
         self._credentials = _parse_credentials(
-            res.data.decode(), "AssumeRoleWithLDAPIdentityResult",
+            res.data.decode(),
+            "AssumeRoleWithLDAPIdentityResult",
         )
 
         return self._credentials
@@ -491,12 +501,18 @@ def retrieve(self):
 
 class WebIdentityClientGrantsProvider(Provider):
     """Base class for WebIdentity and ClientGrants credentials provider."""
+
     __metaclass__ = ABCMeta
 
     def __init__(
-            self, jwt_provider_func, sts_endpoint,
-            duration_seconds=0, policy=None, role_arn=None,
-            role_session_name=None, http_client=None,
+        self,
+        jwt_provider_func,
+        sts_endpoint,
+        duration_seconds=0,
+        policy=None,
+        role_arn=None,
+        role_session_name=None,
+        http_client=None,
     ):
         self._jwt_provider_func = jwt_provider_func
         self._sts_endpoint = sts_endpoint
@@ -529,9 +545,7 @@ def _get_duration_seconds(self, expiry):
         if expiry <= 0:
             return expiry
 
-        return (
-            _MIN_DURATION_SECONDS if expiry < _MIN_DURATION_SECONDS else expiry
-        )
+        return _MIN_DURATION_SECONDS if expiry < _MIN_DURATION_SECONDS else expiry
 
     def retrieve(self):
         """Retrieve credentials."""
@@ -583,11 +597,18 @@ class ClientGrantsProvider(WebIdentityClientGrantsProvider):
     """Credential provider using AssumeRoleWithClientGrants API."""
 
     def __init__(
-            self, jwt_provider_func, sts_endpoint,
-            duration_seconds=0, policy=None, http_client=None,
+        self,
+        jwt_provider_func,
+        sts_endpoint,
+        duration_seconds=0,
+        policy=None,
+        http_client=None,
     ):
         super().__init__(
-            jwt_provider_func, sts_endpoint, duration_seconds, policy,
+            jwt_provider_func,
+            sts_endpoint,
+            duration_seconds,
+            policy,
             http_client=http_client,
         )
 
@@ -606,9 +627,14 @@ class CertificateIdentityProvider(Provider):
     """Credential provider using AssumeRoleWithCertificate API."""
 
     def __init__(
-            self, sts_endpoint, cert_file=None, key_file=None,
-            key_password=None, ca_certs=None, duration_seconds=0,
-            http_client=None,
+        self,
+        sts_endpoint,
+        cert_file=None,
+        key_file=None,
+        key_password=None,
+        ca_certs=None,
+        duration_seconds=0,
+        http_client=None,
     ):
         if urlsplit(sts_endpoint).scheme != "https":
             raise ValueError("STS endpoint scheme must be HTTPS")
@@ -620,21 +646,25 @@ def __init__(
                 "either cert/key file or custom http_client must be provided",
             )
 
-        self._sts_endpoint = sts_endpoint + "?" + urlencode(
-            {
-                "Action": "AssumeRoleWithCertificate",
-                "Version": "2011-06-15",
-                "DurationSeconds": str(
-                    duration_seconds
-                    if duration_seconds > _DEFAULT_DURATION_SECONDS
-                    else _DEFAULT_DURATION_SECONDS
-                ),
-            },
+        self._sts_endpoint = (
+            sts_endpoint
+            + "?"
+            + urlencode(
+                {
+                    "Action": "AssumeRoleWithCertificate",
+                    "Version": "2011-06-15",
+                    "DurationSeconds": str(
+                        duration_seconds
+                        if duration_seconds > _DEFAULT_DURATION_SECONDS
+                        else _DEFAULT_DURATION_SECONDS
+                    ),
+                },
+            )
         )
         self._http_client = http_client or urllib3.PoolManager(
             maxsize=10,
             cert_file=cert_file,
-            cert_reqs='CERT_REQUIRED',
+            cert_reqs="CERT_REQUIRED",
             key_file=key_file,
             key_password=key_password,
             ca_certs=ca_certs or certifi.where(),
@@ -659,7 +689,8 @@ def retrieve(self):
         )
 
         self._credentials = _parse_credentials(
-            res.data.decode(), "AssumeRoleWithCertificateResult",
+            res.data.decode(),
+            "AssumeRoleWithCertificateResult",
         )
 
         return self._credentials
diff --git a/miniopy_async/datatypes.py b/miniopy_async/datatypes.py
index 0e1f9a3..52b0bf5 100644
--- a/miniopy_async/datatypes.py
+++ b/miniopy_async/datatypes.py
@@ -113,11 +113,17 @@ def __init__(
         self,  # pylint: disable=too-many-arguments
         bucket_name,
         object_name,
-        last_modified=None, etag=None,
-        size=None, metadata=None,
-        version_id=None, is_latest=None, storage_class=None,
-        owner_id=None, owner_name=None, content_type=None,
-        is_delete_marker=False
+        last_modified=None,
+        etag=None,
+        size=None,
+        metadata=None,
+        version_id=None,
+        is_latest=None,
+        storage_class=None,
+        owner_id=None,
+        owner_name=None,
+        content_type=None,
+        is_delete_marker=False,
     ):
         self._bucket_name = bucket_name
         self._object_name = object_name
@@ -204,10 +210,7 @@ def content_type(self):
         return self._content_type
 
     @classmethod
-    def fromxml(
-        cls, element, bucket_name, is_delete_marker=False,
-        encoding_type=None
-    ):
+    def fromxml(cls, element, bucket_name, is_delete_marker=False, encoding_type=None):
         """Create new object with values from XML element."""
         tag = findtext(element, "LastModified")
         last_modified = None if tag is None else from_iso8601utc(tag)
@@ -220,7 +223,8 @@ def fromxml(
 
         tag = find(element, "Owner")
         owner_id, owner_name = (
-            (None, None) if tag is None
+            (None, None)
+            if tag is None
             else (findtext(tag, "ID"), findtext(tag, "DisplayName"))
         )
 
@@ -271,16 +275,18 @@ async def parse_list_objects(response, bucket_name=None):
     elements = findall(element, "CommonPrefixes")
     objects += [
         Object(
-            bucket_name, unquote_plus(findtext(tag, "Prefix", True))
-            if encoding_type == "url" else findtext(tag, "Prefix", True)
-        ) for tag in elements
+            bucket_name,
+            unquote_plus(findtext(tag, "Prefix", True))
+            if encoding_type == "url"
+            else findtext(tag, "Prefix", True),
+        )
+        for tag in elements
     ]
 
     elements = findall(element, "DeleteMarker")
     objects += [
         Object.fromxml(
-            tag, bucket_name, is_delete_marker=True,
-            encoding_type=encoding_type
+            tag, bucket_name, is_delete_marker=True, encoding_type=encoding_type
         )
         for tag in elements
     ]
@@ -362,7 +368,7 @@ def __init__(self, part_number, etag, last_modified=None, size=None):
 
     @property
     def part_number(self):
-        """Get part number. """
+        """Get part number."""
         return self._part_number
 
     @property
@@ -397,28 +403,21 @@ def fromxml(cls, element):
 class ListPartsResult:
     """ListParts API result."""
 
-    def __init__(self, response, response_data):
+    def __init__(self, response_data):
         element = ET.fromstring(response_data)
         self._bucket_name = findtext(element, "Bucket")
         self._object_name = findtext(element, "Key")
         tag = find(element, "Initiator")
-        self._initiator_id = (
-            None if tag is None else findtext(tag, "ID")
-        )
-        self._initiator_name = (
-            None if tag is None else findtext(tag, "DisplayName")
-        )
+        self._initiator_id = None if tag is None else findtext(tag, "ID")
+        self._initiator_name = None if tag is None else findtext(tag, "DisplayName")
         tag = find(element, "Owner")
-        self._owner_id = (
-            None if tag is None else findtext(tag, "ID")
-        )
-        self._owner_name = (
-            None if tag is None else findtext(tag, "DisplayName")
-        )
+        self._owner_id = None if tag is None else findtext(tag, "ID")
+        self._owner_name = None if tag is None else findtext(tag, "DisplayName")
         self._storage_class = findtext(element, "StorageClass")
         self._part_number_marker = findtext(element, "PartNumberMarker")
         self._next_part_number_marker = findtext(
-            element, "NextPartNumberMarker",
+            element,
+            "NextPartNumberMarker",
         )
         if self._next_part_number_marker:
             self._next_part_number_marker = int(self._next_part_number_marker)
@@ -427,14 +426,13 @@ def __init__(self, response, response_data):
             self._max_parts = int(self._max_parts)
         self._is_truncated = findtext(element, "IsTruncated")
         self._is_truncated = (
-                self._is_truncated is not None and
-                self._is_truncated.lower() == "true"
+            self._is_truncated is not None and self._is_truncated.lower() == "true"
         )
         self._parts = [Part.fromxml(tag) for tag in findall(element, "Part")]
 
     @classmethod
-    async def from_async_response(cls, response):
-        return cls(response, await response.text())
+    async def from_async_response(cls, response_data):
+        return cls(response_data)
 
     @property
     def bucket_name(self):
@@ -498,30 +496,23 @@ def parts(self):
 
 
 class Upload:
-    """ Upload information of a multipart upload."""
+    """Upload information of a multipart upload."""
 
     def __init__(self, element, encoding_type=None):
         self._encoding_type = encoding_type
         self._object_name = findtext(element, "Key", True)
         self._object_name = (
-            unquote_plus(self._object_name) if self._encoding_type == "url"
+            unquote_plus(self._object_name)
+            if self._encoding_type == "url"
             else self._object_name
         )
         self._upload_id = findtext(element, "UploadId")
         tag = find(element, "Initiator")
-        self._initiator_id = (
-            None if tag is None else findtext(tag, "ID")
-        )
-        self._initiator_name = (
-            None if tag is None else findtext(tag, "DisplayName")
-        )
+        self._initiator_id = None if tag is None else findtext(tag, "ID")
+        self._initiator_name = None if tag is None else findtext(tag, "DisplayName")
         tag = find(element, "Owner")
-        self._owner_id = (
-            None if tag is None else findtext(tag, "ID")
-        )
-        self._owner_name = (
-            None if tag is None else findtext(tag, "DisplayName")
-        )
+        self._owner_id = None if tag is None else findtext(tag, "ID")
+        self._owner_name = None if tag is None else findtext(tag, "DisplayName")
         self._storage_class = findtext(element, "StorageClass")
         self._initiated_time = findtext(element, "Initiated")
         if self._initiated_time:
@@ -571,14 +562,15 @@ def initiated_time(self):
 class ListMultipartUploadsResult:
     """ListMultipartUploads API result."""
 
-    def __init__(self, response, response_data):
+    def __init__(self, response_data):
         element = ET.fromstring(response_data)
         self._encoding_type = findtext(element, "EncodingType")
         self._bucket_name = findtext(element, "Bucket")
         self._key_marker = findtext(element, "KeyMarker")
         if self._key_marker:
             self._key_marker = (
-                unquote_plus(self._key_marker) if self._encoding_type == "url"
+                unquote_plus(self._key_marker)
+                if self._encoding_type == "url"
                 else self._key_marker
             )
         self._upload_id_marker = findtext(element, "UploadIdMarker")
@@ -586,7 +578,8 @@ def __init__(self, response, response_data):
         if self._next_key_marker:
             self._next_key_marker = (
                 unquote_plus(self._next_key_marker)
-                if self._encoding_type == "url" else self._next_key_marker
+                if self._encoding_type == "url"
+                else self._next_key_marker
             )
         self._next_upload_id_marker = findtext(element, "NextUploadIdMarker")
         self._max_uploads = findtext(element, "MaxUploads")
@@ -594,17 +587,15 @@ def __init__(self, response, response_data):
             self._max_uploads = int(self._max_uploads)
         self._is_truncated = findtext(element, "IsTruncated")
         self._is_truncated = (
-                self._is_truncated is not None and
-                self._is_truncated.lower() == "true"
+            self._is_truncated is not None and self._is_truncated.lower() == "true"
         )
         self._uploads = [
-            Upload(tag, self._encoding_type)
-            for tag in findall(element, "Upload")
+            Upload(tag, self._encoding_type) for tag in findall(element, "Upload")
         ]
 
     @classmethod
-    async def from_async_response(cls, response):
-        return cls(response, await response.text())
+    async def from_async_response(cls, response_data):
+        return cls(response_data)
 
     @property
     def bucket_name(self):
@@ -696,14 +687,11 @@ def add_equals_condition(self, element, value):
         if not element:
             raise ValueError("condition element cannot be empty")
         element = _trim_dollar(element)
-        if (
-                element in
-                [
-                    "success_action_redirect",
-                    "redirect",
-                    "content-length-range",
-                ]
-        ):
+        if element in [
+            "success_action_redirect",
+            "redirect",
+            "content-length-range",
+        ]:
             raise ValueError(element + " is unsupported for equals condition")
         if element in _RESERVED_ELEMENTS:
             raise ValueError(element + " cannot be set")
@@ -723,12 +711,8 @@ def add_starts_with_condition(self, element, value):
         if not element:
             raise ValueError("condition element cannot be empty")
         element = _trim_dollar(element)
-        if (
-                element in ["success_action_status", "content-length-range"] or
-                (
-                        element.startswith("x-amz-") and
-                        not element.startswith("x-amz-meta-")
-                )
+        if element in ["success_action_status", "content-length-range"] or (
+            element.startswith("x-amz-") and not element.startswith("x-amz-meta-")
         ):
             raise ValueError(
                 f"{element} is unsupported for starts-with condition",
@@ -773,8 +757,8 @@ def form_data(self, creds, region):
         if not region:
             raise ValueError("region cannot be empty")
         if (
-                "key" not in self._conditions[_EQ] and
-                "key" not in self._conditions[_STARTS_WITH]
+            "key" not in self._conditions[_EQ]
+            and "key" not in self._conditions[_STARTS_WITH]
         ):
             raise ValueError("key condition must be set")
 
@@ -801,7 +785,10 @@ def form_data(self, creds, region):
 
         policy = base64.b64encode(json.dumps(policy).encode())
         signature = post_presign_v4(
-            policy.decode(), creds.secret_key, utcnow, region,
+            policy.decode(),
+            creds.secret_key,
+            utcnow,
+            region,
         )
         form_data = {
             "x-amz-algorithm": _ALGORITHM,
@@ -847,7 +834,7 @@ async def _get_records(self):
         if not line:
             return None
         event = json.loads(line)
-        if event['Records']:
+        if event["Records"]:
             return event
         return None
 
diff --git a/miniopy_async/deleteobjects.py b/miniopy_async/deleteobjects.py
index d85eee5..97692f9 100644
--- a/miniopy_async/deleteobjects.py
+++ b/miniopy_async/deleteobjects.py
@@ -59,9 +59,7 @@ def toxml(self, element):
 class DeletedObject:
     """Deleted object information."""
 
-    def __init__(
-        self, name, version_id, delete_marker, delete_marker_version_id
-    ):
+    def __init__(self, name, version_id, delete_marker, delete_marker_version_id):
         self._name = name
         self._version_id = version_id
         self._delete_marker = delete_marker
@@ -93,9 +91,7 @@ def fromxml(cls, element):
         name = findtext(element, "Key", True)
         version_id = findtext(element, "VersionId")
         delete_marker = findtext(element, "DeleteMarker")
-        delete_marker = (
-                delete_marker is not None and delete_marker.title() == "True"
-        )
+        delete_marker = delete_marker is not None and delete_marker.title() == "True"
         delete_marker_version_id = findtext(element, "DeleteMarkerVersionId")
         return cls(name, version_id, delete_marker, delete_marker_version_id)
 
diff --git a/miniopy_async/error.py b/miniopy_async/error.py
index 2ee4d4b..a9f058a 100644
--- a/miniopy_async/error.py
+++ b/miniopy_async/error.py
@@ -81,8 +81,17 @@ class S3Error(MinioException):
     when executing S3 operation.
     """
 
-    def __init__(self, code, message, resource, request_id, host_id,
-                 response, bucket_name=None, object_name=None):
+    def __init__(
+        self,
+        code,
+        message,
+        resource,
+        request_id,
+        host_id,
+        response,
+        bucket_name=None,
+        object_name=None,
+    ):
         self._code = code
         self._message = message
         self._resource = resource
@@ -93,12 +102,10 @@ def __init__(self, code, message, resource, request_id, host_id,
         self._object_name = object_name
 
         bucket_message = (
-            (", bucket_name: " + self._bucket_name)
-            if self._bucket_name else ""
+            (", bucket_name: " + self._bucket_name) if self._bucket_name else ""
         )
         object_message = (
-            (", object_name: " + self._object_name)
-            if self._object_name else ""
+            (", object_name: " + self._object_name) if self._object_name else ""
         )
         super().__init__(
             f"S3 operation failed; code: {code}, message: {message}, "
@@ -107,9 +114,16 @@ def __init__(self, code, message, resource, request_id, host_id,
         )
 
     def __reduce__(self):
-        return type(self), (self._code, self._message, self._resource,
-                            self._request_id, self._host_id, self._response,
-                            self._bucket_name, self._object_name)
+        return type(self), (
+            self._code,
+            self._message,
+            self._resource,
+            self._request_id,
+            self._host_id,
+            self._response,
+            self._bucket_name,
+            self._object_name,
+        )
 
     @property
     def code(self):
diff --git a/miniopy_async/helpers.py b/miniopy_async/helpers.py
index 4ac7dd0..024183a 100644
--- a/miniopy_async/helpers.py
+++ b/miniopy_async/helpers.py
@@ -44,20 +44,20 @@
 MIN_PART_SIZE = 5 * 1024 * 1024  # 5MiB
 
 _VALID_BUCKETNAME_REGEX = re.compile(
-    '^[A-Za-z0-9][A-Za-z0-9\\.\\-\\_\\:]{1,61}[A-Za-z0-9]$')
-_VALID_BUCKETNAME_STRICT_REGEX = re.compile(
-    '^[a-z0-9][a-z0-9\\.\\-]{1,61}[a-z0-9]$')
-_VALID_IP_ADDRESS = re.compile(
-    r'^(\d+\.){3}\d+$')
+    "^[A-Za-z0-9][A-Za-z0-9\\.\\-\\_\\:]{1,61}[A-Za-z0-9]$"
+)
+_VALID_BUCKETNAME_STRICT_REGEX = re.compile("^[a-z0-9][a-z0-9\\.\\-]{1,61}[a-z0-9]$")
+_VALID_IP_ADDRESS = re.compile(r"^(\d+\.){3}\d+$")
 _ALLOWED_HOSTNAME_REGEX = re.compile(
-    '^((?!-)(?!_)[A-Z_\\d-]{1,63}(?<!-)(?<!_)\\.)*((?!_)(?!-)' +
-    '[A-Z_\\d-]{1,63}(?<!-)(?<!_))$',
-    re.IGNORECASE)
+    "^((?!-)(?!_)[A-Z_\\d-]{1,63}(?<!-)(?<!_)\\.)*((?!_)(?!-)"
+    + "[A-Z_\\d-]{1,63}(?<!-)(?<!_))$",
+    re.IGNORECASE,
+)
 
-_EXTRACT_REGION_REGEX = re.compile('s3[.-]?(.+?).amazonaws.com')
+_EXTRACT_REGION_REGEX = re.compile("s3[.-]?(.+?).amazonaws.com")
 
 
-def quote(resource, safe='/', encoding=None, errors=None):
+def quote(resource, safe="/", encoding=None, errors=None):
     """
     Wrapper to urllib.parse.quote() replacing back to '~' for older python
     versions.
@@ -70,7 +70,7 @@ def quote(resource, safe='/', encoding=None, errors=None):
     ).replace("%7E", "~")
 
 
-def queryencode(query, safe='', encoding=None, errors=None):
+def queryencode(query, safe="", encoding=None, errors=None):
     """Encode query parameter value."""
     return quote(query, safe, encoding, errors)
 
@@ -89,8 +89,11 @@ def headers_to_strings(headers, titled_key=False):
                         "Signature=*REDACTED*",
                         value if isinstance(value, str) else str(value),
                     ),
-                ) if titled_key else value,
-            ) for key, value in headers.items()
+                )
+                if titled_key
+                else value,
+            )
+            for key, value in headers.items()
         ]
     )
 
@@ -114,10 +117,9 @@ def _validate_sizes(object_size, part_size):
     if object_size >= 0:
         if object_size > MAX_MULTIPART_OBJECT_SIZE:
             raise ValueError(
-                (
-                    "object size {0} is not supported; "
-                    "maximum allowed 5TiB"
-                ).format(object_size),
+                ("object size {0} is not supported; " "maximum allowed 5TiB").format(
+                    object_size
+                ),
             )
     elif part_size <= 0:
         raise ValueError(
@@ -136,9 +138,12 @@ def _get_part_info(object_size, part_size):
         part_size = min(part_size, object_size)
         return part_size, math.ceil(object_size / part_size) if part_size else 1
 
-    part_size = math.ceil(
-        math.ceil(object_size / MAX_MULTIPART_COUNT) / MIN_PART_SIZE,
-    ) * MIN_PART_SIZE
+    part_size = (
+        math.ceil(
+            math.ceil(object_size / MAX_MULTIPART_COUNT) / MIN_PART_SIZE,
+        )
+        * MIN_PART_SIZE
+    )
     return part_size, math.ceil(object_size / part_size) if part_size else 1
 
 
@@ -155,7 +160,7 @@ def get_part_info(object_size, part_size):
     return part_size, part_count
 
 
-async def read_part_data(stream, size, part_data=b''):
+async def read_part_data(stream, size, part_data=b""):
     """Read part data of given size from stream."""
     is_co_function = asyncio.iscoroutinefunction(stream.read)
     buffer = io.BytesIO()
@@ -192,36 +197,38 @@ def check_bucket_name(bucket_name, strict=False):
     # Verify bucket name is not empty
     bucket_name = str(bucket_name).strip()
     if not bucket_name:
-        raise ValueError('Bucket name cannot be empty.')
+        raise ValueError("Bucket name cannot be empty.")
 
     # Verify bucket name length.
     if len(bucket_name) < 3:
-        raise ValueError('Bucket name cannot be less than'
-                         ' 3 characters.')
+        raise ValueError("Bucket name cannot be less than" " 3 characters.")
     if len(bucket_name) > 63:
-        raise ValueError('Bucket name cannot be greater than'
-                         ' 63 characters.')
+        raise ValueError("Bucket name cannot be greater than" " 63 characters.")
 
     match = _VALID_IP_ADDRESS.match(bucket_name)
     if match:
-        raise ValueError('Bucket name cannot be an ip address')
+        raise ValueError("Bucket name cannot be an ip address")
 
-    unallowed_successive_chars = ['..', '.-', '-.']
+    unallowed_successive_chars = ["..", ".-", "-."]
     if any(x in bucket_name for x in unallowed_successive_chars):
-        raise ValueError('Bucket name contains invalid '
-                         'successive chars '
-                         + str(unallowed_successive_chars) + '.')
+        raise ValueError(
+            "Bucket name contains invalid "
+            "successive chars " + str(unallowed_successive_chars) + "."
+        )
 
     if strict:
         match = _VALID_BUCKETNAME_STRICT_REGEX.match(bucket_name)
         if (not match) or match.end() != len(bucket_name):
-            raise ValueError('Bucket name contains invalid '
-                             'characters (strictly enforced).')
+            raise ValueError(
+                "Bucket name contains invalid " "characters (strictly enforced)."
+            )
 
     match = _VALID_BUCKETNAME_REGEX.match(bucket_name)
     if (not match) or match.end() != len(bucket_name):
-        raise ValueError('Bucket name does not follow S3 standards.'
-                         ' Bucket: {0}'.format(bucket_name))
+        raise ValueError(
+            "Bucket name does not follow S3 standards."
+            " Bucket: {0}".format(bucket_name)
+        )
 
 
 def check_non_empty_string(string):
@@ -276,13 +283,13 @@ def sha256_hash(data):
     """Compute SHA-256 of data and return hash as hex encoded value."""
     if data is None:
         return "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
-    sha256sum = hashlib.sha256(data.encode() if isinstance(data, str) else data).hexdigest()
+    sha256sum = hashlib.sha256(
+        data.encode() if isinstance(data, str) else data
+    ).hexdigest()
     return sha256sum.decode() if isinstance(sha256sum, bytes) else sha256sum
 
 
-def url_replace(
-        url, scheme=None, netloc=None, path=None, query=None, fragment=None
-):
+def url_replace(url, scheme=None, netloc=None, path=None, query=None, fragment=None):
     """Return new URL with replaced properties in given URL."""
     return urllib.parse.SplitResult(
         scheme if scheme is not None else url.scheme,
@@ -315,9 +322,9 @@ def to_string(value):
         return value
 
     def normalize_value(value):
-        #if not isinstance(values, (list, tuple)):
+        # if not isinstance(values, (list, tuple)):
         #    values = [values]
-        #return [to_string(value) for value in values]
+        # return [to_string(value) for value in values]
         return to_string(value)
 
     return {
@@ -333,19 +340,19 @@ def normalize_headers(headers):
     def guess_user_metadata(key):
         key = key.lower()
         return not (
-                key.startswith("x-amz-") or
-                key in [
-                    "cache-control",
-                    "content-encoding",
-                    "content-type",
-                    "content-disposition",
-                    "content-language",
-                ]
+            key.startswith("x-amz-")
+            or key
+            in [
+                "cache-control",
+                "content-encoding",
+                "content-type",
+                "content-disposition",
+                "content-language",
+            ]
         )
 
     user_metadata = {
-        key: value for key, value in headers.items()
-        if guess_user_metadata(key)
+        key: value for key, value in headers.items() if guess_user_metadata(key)
     }
 
     # Remove guessed user metadata.
@@ -369,8 +376,8 @@ def genheaders(headers, sse, tags, retention, legal_hold):
         headers["x-amz-tagging"] = tagging
     if retention and retention.mode:
         headers["x-amz-object-lock-mode"] = retention.mode
-        headers["x-amz-object-lock-retain-until-date"] = (
-            to_iso8601utc(retention.retain_until_date)
+        headers["x-amz-object-lock-retain-until-date"] = to_iso8601utc(
+            retention.retain_until_date
         )
     if legal_hold:
         headers["x-amz-object-lock-legal-hold"] = "ON"
@@ -429,35 +436,23 @@ def __init__(self, endpoint, region):
         if url.password:
             raise ValueError("password in endpoint is not allowed")
 
-        if (
-                (url.scheme == "http" and url.port == 80) or
-                (url.scheme == "https" and url.port == 443)
+        if (url.scheme == "http" and url.port == 80) or (
+            url.scheme == "https" and url.port == 443
         ):
             url = url_replace(url, netloc=host)
 
         self._accelerate_host_flag = host.startswith("s3-accelerate.")
-        self._is_aws_host = (
-                (
-                        host.startswith("s3.") or self._accelerate_host_flag
-                ) and
-                (
-                        host.endswith(".amazonaws.com") or
-                        host.endswith(".amazonaws.com.cn")
-                )
-        )
-        self._virtual_style_flag = (
-                self._is_aws_host or host.endswith("aliyuncs.com")
+        self._is_aws_host = (host.startswith("s3.") or self._accelerate_host_flag) and (
+            host.endswith(".amazonaws.com") or host.endswith(".amazonaws.com.cn")
         )
+        self._virtual_style_flag = self._is_aws_host or host.endswith("aliyuncs.com")
 
         region_in_host = None
         if self._is_aws_host:
             is_aws_china_host = host.endswith(".cn")
             url = url_replace(
                 url,
-                netloc=(
-                    "amazonaws.com.cn"
-                    if is_aws_china_host else "amazonaws.com"
-                ),
+                netloc=("amazonaws.com.cn" if is_aws_china_host else "amazonaws.com"),
             )
             region_in_host = _extract_region(host)
 
@@ -527,8 +522,12 @@ def virtual_style_flag(self, flag):
         self._virtual_style_flag = flag
 
     def build(
-            self, method, region,
-            bucket_name=None, object_name=None, query_params=None,
+        self,
+        method,
+        region,
+        bucket_name=None,
+        object_name=None,
+        query_params=None,
     ):
         """Build URL for given information."""
 
@@ -551,19 +550,20 @@ def build(
             url = url_replace(url, path="/")
             return (
                 url_replace(url, netloc="s3." + region + "." + host)
-                if self._is_aws_host else url
+                if self._is_aws_host
+                else url
             )
 
         enforce_path_style = (
             # CreateBucket API requires path style in Amazon AWS S3.
-                (method == "PUT" and not object_name and not query_params) or
-
-                # GetBucketLocation API requires path style in Amazon AWS S3.
-                (query_params and "location" in query_params) or
-
-                # Use path style for bucket name containing '.' which causes
-                # SSL certificate validation error.
-                ("." in bucket_name and self._url.scheme == "https")
+            (method == "PUT" and not object_name and not query_params)
+            or
+            # GetBucketLocation API requires path style in Amazon AWS S3.
+            (query_params and "location" in query_params)
+            or
+            # Use path style for bucket name containing '.' which causes
+            # SSL certificate validation error.
+            ("." in bucket_name and self._url.scheme == "https")
         )
 
         if self._is_aws_host:
@@ -608,8 +608,14 @@ class ObjectWriteResult:
     """Result class of any APIs doing object creation."""
 
     def __init__(
-            self, bucket_name, object_name, version_id, etag, http_headers,
-            last_modified=None, location=None,
+        self,
+        bucket_name,
+        object_name,
+        version_id,
+        etag,
+        http_headers,
+        last_modified=None,
+        location=None,
     ):
         self._bucket_name = bucket_name
         self._object_name = object_name
diff --git a/miniopy_async/lifecycleconfig.py b/miniopy_async/lifecycleconfig.py
index 24df58b..7029bd4 100644
--- a/miniopy_async/lifecycleconfig.py
+++ b/miniopy_async/lifecycleconfig.py
@@ -33,6 +33,7 @@
 
 class DateDays:
     """Base class holds date and days of Transition and Expiration."""
+
     __metaclass__ = ABCMeta
 
     def __init__(self, date=None, days=None):
@@ -62,7 +63,9 @@ def toxml(self, element):
         """Convert to XML."""
         if self._date is not None:
             SubElement(
-                element, "Date", to_iso8601utc(self._date),
+                element,
+                "Date",
+                to_iso8601utc(self._date),
             )
         if self._days:
             SubElement(element, "Days", str(self._days))
@@ -164,8 +167,7 @@ def toxml(self, element):
 class Expiration(DateDays):
     """Expiration."""
 
-    def __init__(self, date=None, days=None,
-                 expired_object_delete_marker=None):
+    def __init__(self, date=None, days=None, expired_object_delete_marker=None):
         super().__init__(date, days)
         self._expired_object_delete_marker = expired_object_delete_marker
 
@@ -180,13 +182,13 @@ def fromxml(cls, element):
         element = find(element, "Expiration")
         date, days = cls.parsexml(element)
         expired_object_delete_marker = findtext(
-            element, "ExpiredObjectDeleteMarker",
+            element,
+            "ExpiredObjectDeleteMarker",
         )
         if expired_object_delete_marker is not None:
             if expired_object_delete_marker.title() not in ["False", "True"]:
                 raise ValueError(
-                    "value of ExpiredObjectDeleteMarker must be "
-                    "'True' or 'False'",
+                    "value of ExpiredObjectDeleteMarker must be " "'True' or 'False'",
                 )
             expired_object_delete_marker = (
                 expired_object_delete_marker.title() == "True"
@@ -240,13 +242,19 @@ def toxml(self, element):
 
 
 class Rule(BaseRule):
-    """Lifecycle rule. """
-
-    def __init__(self, status, abort_incomplete_multipart_upload=None,
-                 expiration=None, rule_filter=None, rule_id=None,
-                 noncurrent_version_expiration=None,
-                 noncurrent_version_transition=None,
-                 transition=None):
+    """Lifecycle rule."""
+
+    def __init__(
+        self,
+        status,
+        abort_incomplete_multipart_upload=None,
+        expiration=None,
+        rule_filter=None,
+        rule_id=None,
+        noncurrent_version_expiration=None,
+        noncurrent_version_transition=None,
+        transition=None,
+    ):
         check_status(status)
         if not rule_filter:
             raise ValueError("Rule filter must be provided")
@@ -254,9 +262,7 @@ def __init__(self, status, abort_incomplete_multipart_upload=None,
         super().__init__(rule_filter, rule_id)
 
         self._status = status
-        self._abort_incomplete_multipart_upload = (
-            abort_incomplete_multipart_upload
-        )
+        self._abort_incomplete_multipart_upload = abort_incomplete_multipart_upload
         self._expiration = expiration
         self._noncurrent_version_expiration = noncurrent_version_expiration
         self._noncurrent_version_transition = noncurrent_version_transition
@@ -297,32 +303,31 @@ def fromxml(cls, element):
         """Create new object with values from XML element."""
         status = findtext(element, "Status", True)
         abort_incomplete_multipart_upload = (
-            None if find(element, "AbortIncompleteMultipartUpload") is None
+            None
+            if find(element, "AbortIncompleteMultipartUpload") is None
             else AbortIncompleteMultipartUpload.fromxml(element)
         )
         expiration = (
-            None if find(element, "Expiration") is None
-            else Expiration.fromxml(element)
+            None if find(element, "Expiration") is None else Expiration.fromxml(element)
         )
         rule_filter, rule_id = cls.parsexml(element)
         noncurrent_version_expiration = (
-            None if find(element, "NoncurrentVersionExpiration") is None
+            None
+            if find(element, "NoncurrentVersionExpiration") is None
             else NoncurrentVersionExpiration.fromxml(element)
         )
         noncurrent_version_transition = (
-            None if find(element, "NoncurrentVersionTransition") is None
+            None
+            if find(element, "NoncurrentVersionTransition") is None
             else NoncurrentVersionTransition.fromxml(element)
         )
         transition = (
-            None if find(element, "Transition") is None
-            else Transition.fromxml(element)
+            None if find(element, "Transition") is None else Transition.fromxml(element)
         )
 
         return cls(
             status,
-            abort_incomplete_multipart_upload=(
-                abort_incomplete_multipart_upload
-            ),
+            abort_incomplete_multipart_upload=(abort_incomplete_multipart_upload),
             expiration=expiration,
             rule_filter=rule_filter,
             rule_id=rule_id,
diff --git a/miniopy_async/minioadmin.py b/miniopy_async/minioadmin.py
index 5e58e77..3b43eab 100644
--- a/miniopy_async/minioadmin.py
+++ b/miniopy_async/minioadmin.py
@@ -30,9 +30,13 @@ class MinioAdmin:
     """MinIO Admin wrapper using MinIO Client (mc) tool."""
 
     def __init__(
-            self, target,
-            binary_path=None, config_dir=None, ignore_cert_check=False,
-            timeout=None, env=None,
+        self,
+        target,
+        binary_path=None,
+        config_dir=None,
+        ignore_cert_check=False,
+        timeout=None,
+        env=None,
     ):
         self._target = target
         self._timeout = timeout
@@ -149,7 +153,10 @@ def policy_set(self, policy_name, user=None, group=None):
         if (user is not None) ^ (group is not None):
             return self._run(
                 [
-                    "policy", "set", self._target, policy_name,
+                    "policy",
+                    "set",
+                    self._target,
+                    policy_name,
                     ("user=" if user else "group=") + (user or group),
                 ],
             )
@@ -208,27 +215,33 @@ def prometheus_generate(self):
     def kms_key_create(self, key=None):
         """Create a new KMS master key."""
         return self._run(
-            [
-                "kms", "key", "create", self._target, key
-            ] + ([key] if key else []),
+            ["kms", "key", "create", self._target, key] + ([key] if key else []),
         )
 
     def kms_key_status(self, key=None):
         """Get status information of a KMS master key."""
         return self._run(
-            [
-                "kms", "key", "status", self._target, key
-            ] + ([key] if key else []),
+            ["kms", "key", "status", self._target, key] + ([key] if key else []),
         )
 
     def bucket_remote_add(
-            self, src_bucket, dest_url,
-            path=None, region=None, bandwidth=None, service=None,
+        self,
+        src_bucket,
+        dest_url,
+        path=None,
+        region=None,
+        bandwidth=None,
+        service=None,
     ):
         """Add a new remote target."""
         args = [
-            "bucket", "remote", "add", self._target + "/" + src_bucket,
-            dest_url, "--service", service or "replication",
+            "bucket",
+            "remote",
+            "add",
+            self._target + "/" + src_bucket,
+            dest_url,
+            "--service",
+            service or "replication",
         ]
         if path:
             args += ["--path", path]
@@ -242,8 +255,13 @@ def bucket_remote_edit(self, src_bucket, dest_url, arn):
         """Edit credentials of remote target."""
         return self._run(
             [
-                "bucket", "remote", "edit", self._target + "/" + src_bucket,
-                dest_url, "--arn", arn,
+                "bucket",
+                "remote",
+                "edit",
+                self._target + "/" + src_bucket,
+                dest_url,
+                "--arn",
+                arn,
             ],
         )
 
@@ -251,9 +269,12 @@ def bucket_remote_list(self, src_bucket=None, service=None):
         """List remote targets."""
         return self._run(
             [
-                "bucket", "remote", "ls",
+                "bucket",
+                "remote",
+                "ls",
                 self._target + ("/" + src_bucket if src_bucket else ""),
-                "--service", service or "replication",
+                "--service",
+                service or "replication",
             ],
         )
 
@@ -261,8 +282,12 @@ def bucket_remote_remove(self, src_bucket, arn):
         """Remove configured remote target."""
         return self._run(
             [
-                "bucket", "remote", "rm", self._target + "/" + src_bucket,
-                "--arn", arn,
+                "bucket",
+                "remote",
+                "rm",
+                self._target + "/" + src_bucket,
+                "--arn",
+                arn,
             ],
         )
 
diff --git a/miniopy_async/notificationconfig.py b/miniopy_async/notificationconfig.py
index 364a462..b1a0f17 100644
--- a/miniopy_async/notificationconfig.py
+++ b/miniopy_async/notificationconfig.py
@@ -81,8 +81,7 @@ class CommonConfig:
 
     __metaclass__ = ABCMeta
 
-    def __init__(self, events, config_id, prefix_filter_rule,
-                 suffix_filter_rule):
+    def __init__(self, events, config_id, prefix_filter_rule, suffix_filter_rule):
         if not events:
             raise ValueError("events must be provided")
         self._events = events
@@ -149,13 +148,22 @@ def toxml(self, element):
 class CloudFuncConfig(CommonConfig):
     """Cloud function configuration."""
 
-    def __init__(self, cloud_func, events, config_id=None,
-                 prefix_filter_rule=None, suffix_filter_rule=None):
+    def __init__(
+        self,
+        cloud_func,
+        events,
+        config_id=None,
+        prefix_filter_rule=None,
+        suffix_filter_rule=None,
+    ):
         if not cloud_func:
             raise ValueError("cloud function must be provided")
         self._cloud_func = cloud_func
         super().__init__(
-            events, config_id, prefix_filter_rule, suffix_filter_rule,
+            events,
+            config_id,
+            prefix_filter_rule,
+            suffix_filter_rule,
         )
 
     @property
@@ -167,14 +175,11 @@ def cloud_func(self):
     def fromxml(cls, element):
         """Create new object with values from XML element."""
         cloud_func = findtext(element, "CloudFunction", True)
-        (events, config_id, prefix_filter_rule,
-         suffix_filter_rule) = cls.parsexml(element)
+        (events, config_id, prefix_filter_rule, suffix_filter_rule) = cls.parsexml(
+            element
+        )
         return cls(
-            cloud_func,
-            events,
-            config_id,
-            prefix_filter_rule,
-            suffix_filter_rule
+            cloud_func, events, config_id, prefix_filter_rule, suffix_filter_rule
         )
 
     def toxml(self, element):
@@ -188,13 +193,22 @@ def toxml(self, element):
 class QueueConfig(CommonConfig):
     """Queue configuration."""
 
-    def __init__(self, queue, events, config_id=None,
-                 prefix_filter_rule=None, suffix_filter_rule=None):
+    def __init__(
+        self,
+        queue,
+        events,
+        config_id=None,
+        prefix_filter_rule=None,
+        suffix_filter_rule=None,
+    ):
         if not queue:
             raise ValueError("queue must be provided")
         self._queue = queue
         super().__init__(
-            events, config_id, prefix_filter_rule, suffix_filter_rule,
+            events,
+            config_id,
+            prefix_filter_rule,
+            suffix_filter_rule,
         )
 
     @property
@@ -206,15 +220,10 @@ def queue(self):
     def fromxml(cls, element):
         """Create new object with values from XML element."""
         queue = findtext(element, "Queue", True)
-        (events, config_id, prefix_filter_rule,
-         suffix_filter_rule) = cls.parsexml(element)
-        return cls(
-            queue,
-            events,
-            config_id,
-            prefix_filter_rule,
-            suffix_filter_rule
+        (events, config_id, prefix_filter_rule, suffix_filter_rule) = cls.parsexml(
+            element
         )
+        return cls(queue, events, config_id, prefix_filter_rule, suffix_filter_rule)
 
     def toxml(self, element):
         """Convert to XML."""
@@ -227,13 +236,22 @@ def toxml(self, element):
 class TopicConfig(CommonConfig):
     """Get topic configuration."""
 
-    def __init__(self, topic, events, config_id=None,
-                 prefix_filter_rule=None, suffix_filter_rule=None):
+    def __init__(
+        self,
+        topic,
+        events,
+        config_id=None,
+        prefix_filter_rule=None,
+        suffix_filter_rule=None,
+    ):
         if not topic:
             raise ValueError("topic must be provided")
         self._topic = topic
         super().__init__(
-            events, config_id, prefix_filter_rule, suffix_filter_rule,
+            events,
+            config_id,
+            prefix_filter_rule,
+            suffix_filter_rule,
         )
 
     @property
@@ -245,15 +263,10 @@ def topic(self):
     def fromxml(cls, element):
         """Create new object with values from XML element."""
         topic = findtext(element, "Topic", True)
-        (events, config_id, prefix_filter_rule,
-         suffix_filter_rule) = cls.parsexml(element)
-        return cls(
-            topic,
-            events,
-            config_id,
-            prefix_filter_rule,
-            suffix_filter_rule
+        (events, config_id, prefix_filter_rule, suffix_filter_rule) = cls.parsexml(
+            element
         )
+        return cls(topic, events, config_id, prefix_filter_rule, suffix_filter_rule)
 
     def toxml(self, element):
         """Convert to XML."""
@@ -266,8 +279,12 @@ def toxml(self, element):
 class NotificationConfig:
     """Notification configuration."""
 
-    def __init__(self, cloud_func_config_list=None, queue_config_list=None,
-                 topic_config_list=None):
+    def __init__(
+        self,
+        cloud_func_config_list=None,
+        queue_config_list=None,
+        topic_config_list=None,
+    ):
         self._cloud_func_config_list = cloud_func_config_list or []
         self._queue_config_list = queue_config_list or []
         self._topic_config_list = topic_config_list or []
@@ -303,7 +320,9 @@ def fromxml(cls, element):
         for tag in elements:
             topic_config_list.append(TopicConfig.fromxml(tag))
         return cls(
-            cloud_func_config_list, queue_config_list, topic_config_list,
+            cloud_func_config_list,
+            queue_config_list,
+            topic_config_list,
         )
 
     def toxml(self, element):
diff --git a/miniopy_async/progress.py b/miniopy_async/progress.py
index 4b16bb8..5e87852 100644
--- a/miniopy_async/progress.py
+++ b/miniopy_async/progress.py
@@ -27,36 +27,36 @@
 
 _BAR_SIZE = 20
 _KILOBYTE = 1024
-_FINISHED_BAR = '#'
-_REMAINING_BAR = '-'
+_FINISHED_BAR = "#"
+_REMAINING_BAR = "-"
 
-_UNKNOWN_SIZE = '?'
-_STR_MEGABYTE = ' MB'
+_UNKNOWN_SIZE = "?"
+_STR_MEGABYTE = " MB"
 
-_HOURS_OF_ELAPSED = '%d:%02d:%02d'
-_MINUTES_OF_ELAPSED = '%02d:%02d'
+_HOURS_OF_ELAPSED = "%d:%02d:%02d"
+_MINUTES_OF_ELAPSED = "%02d:%02d"
 
-_RATE_FORMAT = '%5.2f'
-_PERCENTAGE_FORMAT = '%3d%%'
-_HUMANINZED_FORMAT = '%0.2f'
+_RATE_FORMAT = "%5.2f"
+_PERCENTAGE_FORMAT = "%3d%%"
+_HUMANINZED_FORMAT = "%0.2f"
 
-_DISPLAY_FORMAT = '|%s| %s/%s %s [elapsed: %s left: %s, %s MB/sec]'
+_DISPLAY_FORMAT = "|%s| %s/%s %s [elapsed: %s left: %s, %s MB/sec]"
 
-_REFRESH_CHAR = '\r'
+_REFRESH_CHAR = "\r"
 
 
 class Progress:
     """
-        Constructs a :class:`Progress` object.
-        :param interval: Sets the time interval to be displayed on the screen.
-        :param stdout: Sets the standard output
-        :return: :class:`Progress` object
+    Constructs a :class:`Progress` object.
+    :param interval: Sets the time interval to be displayed on the screen.
+    :param stdout: Sets the standard output
+    :return: :class:`Progress` object
     """
 
     def __init__(self, object_name, total_length):
         self.object_name = object_name
         self.total_length = total_length
-        self.prefix = self.object_name + ': ' if self.object_name else ''
+        self.prefix = self.object_name + ": " if self.object_name else ""
 
         self.interval = 1
         self.last_printed_len = 0
@@ -72,8 +72,7 @@ def update(self, size):
         """
         if not isinstance(size, int):
             raise ValueError(
-                f'{type(size)} type can not be displayed. '
-                'Please change it to Int.'
+                f"{type(size)} type can not be displayed. " "Please change it to Int."
             )
 
         displayed_time = time.time() - self.initial_time
@@ -82,7 +81,7 @@ def update(self, size):
             current_size=self.current_size,
             total_length=self.total_length,
             displayed_time=displayed_time,
-            prefix=self.prefix
+            prefix=self.prefix,
         )
 
     def print_status(self, current_size, total_length, displayed_time, prefix):
@@ -90,8 +89,9 @@ def print_status(self, current_size, total_length, displayed_time, prefix):
             current_size, total_length, displayed_time
         )
         print(
-            _REFRESH_CHAR + formatted_str + ' ' *
-            max(self.last_printed_len - len(formatted_str), 0)
+            _REFRESH_CHAR
+            + formatted_str
+            + " " * max(self.last_printed_len - len(formatted_str), 0)
         )
         self.last_printed_len = len(formatted_str)
 
@@ -121,38 +121,33 @@ def format_string(current_size, total_length, elapsed_time):
     n_to_mb = current_size / _KILOBYTE / _KILOBYTE
     elapsed_str = seconds_to_time(elapsed_time)
 
-    rate = _RATE_FORMAT % (
-            n_to_mb / elapsed_time
-    ) if elapsed_time else _UNKNOWN_SIZE
+    rate = _RATE_FORMAT % (n_to_mb / elapsed_time) if elapsed_time else _UNKNOWN_SIZE
 
     frac = float(current_size) / total_length
     bar_length = int(frac * _BAR_SIZE)
 
-    bar = (
-            _FINISHED_BAR * bar_length +
-            _REMAINING_BAR * (_BAR_SIZE - bar_length)
-    )
+    bar = _FINISHED_BAR * bar_length + _REMAINING_BAR * (_BAR_SIZE - bar_length)
 
     percentage = _PERCENTAGE_FORMAT % (frac * 100)
 
     left_str = (
-        seconds_to_time(
-            elapsed_time / current_size * (total_length - current_size)
-        )
-        if current_size else _UNKNOWN_SIZE
+        seconds_to_time(elapsed_time / current_size * (total_length - current_size))
+        if current_size
+        else _UNKNOWN_SIZE
     )
 
-    humanized_total = _HUMANINZED_FORMAT % (
-            total_length / _KILOBYTE / _KILOBYTE
-    ) + _STR_MEGABYTE
+    humanized_total = (
+        _HUMANINZED_FORMAT % (total_length / _KILOBYTE / _KILOBYTE) + _STR_MEGABYTE
+    )
 
     humanized_n = _HUMANINZED_FORMAT % n_to_mb + _STR_MEGABYTE
 
     return _DISPLAY_FORMAT % (
-        bar, humanized_n,
+        bar,
+        humanized_n,
         humanized_total,
         percentage,
         elapsed_str,
         left_str,
-        rate
+        rate,
     )
diff --git a/miniopy_async/replicationconfig.py b/miniopy_async/replicationconfig.py
index b40db39..2a8fb3e 100644
--- a/miniopy_async/replicationconfig.py
+++ b/miniopy_async/replicationconfig.py
@@ -28,6 +28,7 @@
 
 class Status:
     """Status."""
+
     __metaclass__ = ABCMeta
 
     def __init__(self, status):
@@ -72,7 +73,8 @@ def fromxml(cls, element):
         """Create new object with values from XML element."""
         element = find(element, "SourceSelectionCriteria")
         return cls(
-            None if find(element, "SseKmsEncryptedObjects") is None
+            None
+            if find(element, "SseKmsEncryptedObjects") is None
             else SseKmsEncryptedObjects.fromxml(element)
         )
 
@@ -97,6 +99,7 @@ def __init__(self, status=DISABLED):
 
 class ReplicationTimeValue:
     """Replication time value."""
+
     __metaclass__ = ABCMeta
 
     def __init__(self, minutes=15):
@@ -257,10 +260,16 @@ def toxml(self, element):
 class Destination:
     """Replication destination."""
 
-    def __init__(self, bucket_arn,
-                 access_control_translation=None, account=None,
-                 encryption_config=None, metrics=None,
-                 replication_time=None, storage_class=None):
+    def __init__(
+        self,
+        bucket_arn,
+        access_control_translation=None,
+        account=None,
+        encryption_config=None,
+        metrics=None,
+        replication_time=None,
+        storage_class=None,
+    ):
         if not bucket_arn:
             raise ValueError("bucket ARN must be provided")
         self._bucket_arn = bucket_arn
@@ -278,7 +287,7 @@ def bucket_arn(self):
 
     @property
     def access_control_translation(self):
-        """Get access control translation. """
+        """Get access control translation."""
         return self._access_control_translation
 
     @property
@@ -311,26 +320,33 @@ def fromxml(cls, element):
         """Create new object with values from XML element."""
         element = find(element, "Destination")
         access_control_translation = (
-            None if find(element, "AccessControlTranslation") is None
+            None
+            if find(element, "AccessControlTranslation") is None
             else AccessControlTranslation.fromxml(element)
         )
         account = findtext(element, "Account")
         bucket_arn = findtext(element, "Bucket", True)
         encryption_config = (
-            None if find(element, "EncryptionConfiguration") is None
+            None
+            if find(element, "EncryptionConfiguration") is None
             else EncryptionConfig.fromxml(element)
         )
-        metrics = (
-            None if find(element, "Metrics") is None
-            else Metrics.fromxml(element)
-        )
+        metrics = None if find(element, "Metrics") is None else Metrics.fromxml(element)
         replication_time = (
-            None if find(element, "ReplicationTime") is None
+            None
+            if find(element, "ReplicationTime") is None
             else ReplicationTime.fromxml(element)
         )
         storage_class = findtext(element, "StorageClass")
-        return cls(bucket_arn, access_control_translation, account,
-                   encryption_config, metrics, replication_time, storage_class)
+        return cls(
+            bucket_arn,
+            access_control_translation,
+            account,
+            encryption_config,
+            metrics,
+            replication_time,
+            storage_class,
+        )
 
     def toxml(self, element):
         """Convert to XML."""
@@ -352,13 +368,20 @@ def toxml(self, element):
 
 
 class Rule(BaseRule):
-    """Replication rule. """
-
-    def __init__(self, destination, status,
-                 delete_marker_replication=None,
-                 existing_object_replication=None,
-                 rule_filter=None, rule_id=None, prefix=None,
-                 priority=None, source_selection_criteria=None):
+    """Replication rule."""
+
+    def __init__(
+        self,
+        destination,
+        status,
+        delete_marker_replication=None,
+        existing_object_replication=None,
+        rule_filter=None,
+        rule_id=None,
+        prefix=None,
+        priority=None,
+        source_selection_criteria=None,
+    ):
         if not destination:
             raise ValueError("destination must be provided")
 
@@ -415,12 +438,14 @@ def source_selection_criteria(self):
     def fromxml(cls, element):
         """Create new object with values from XML element."""
         delete_marker_replication = (
-            None if find(element, "DeleteMarkerReplication") is None
+            None
+            if find(element, "DeleteMarkerReplication") is None
             else DeleteMarkerReplication.fromxml(element)
         )
         destination = Destination.fromxml(element)
         existing_object_replication = (
-            None if find(element, "ExistingObjectReplication") is None
+            None
+            if find(element, "ExistingObjectReplication") is None
             else ExistingObjectReplication.fromxml(element)
         )
         rule_filter, rule_id = cls.parsexml(element)
@@ -429,14 +454,23 @@ def fromxml(cls, element):
         if priority:
             priority = int(priority)
         source_selection_criteria = (
-            None if find(element, "SourceSelectionCriteria") is None
+            None
+            if find(element, "SourceSelectionCriteria") is None
             else SourceSelectionCriteria.fromxml(element)
         )
         status = findtext(element, "Status", True)
 
-        return cls(destination, status, delete_marker_replication,
-                   existing_object_replication, rule_filter,
-                   rule_id, prefix, priority, source_selection_criteria)
+        return cls(
+            destination,
+            status,
+            delete_marker_replication,
+            existing_object_replication,
+            rule_filter,
+            rule_id,
+            prefix,
+            priority,
+            source_selection_criteria,
+        )
 
     def toxml(self, element):
         """Convert to XML."""
diff --git a/miniopy_async/select.py b/miniopy_async/select.py
index 5455ea7..89d4f49 100644
--- a/miniopy_async/select.py
+++ b/miniopy_async/select.py
@@ -52,14 +52,11 @@ class InputSerialization:
     __metaclass__ = ABCMeta
 
     def __init__(self, compression_type):
-        if (
-                compression_type is not None and
-                compression_type not in [
-                    COMPRESSION_TYPE_NONE,
-                    COMPRESSION_TYPE_GZIP,
-                    COMPRESSION_TYPE_BZIP2,
-                ]
-        ):
+        if compression_type is not None and compression_type not in [
+            COMPRESSION_TYPE_NONE,
+            COMPRESSION_TYPE_GZIP,
+            COMPRESSION_TYPE_BZIP2,
+        ]:
             raise ValueError(
                 "compression type must be {0}, {1} or {2}".format(
                     COMPRESSION_TYPE_NONE,
@@ -79,23 +76,26 @@ def toxml(self, element):
 class CSVInputSerialization(InputSerialization):
     """CSV input serialization."""
 
-    def __init__(self, compression_type=None,
-                 allow_quoted_record_delimiter=None, comments=None,
-                 field_delimiter=None, file_header_info=None,
-                 quote_character=None, quote_escape_character=None,
-                 record_delimiter=None):
+    def __init__(
+        self,
+        compression_type=None,
+        allow_quoted_record_delimiter=None,
+        comments=None,
+        field_delimiter=None,
+        file_header_info=None,
+        quote_character=None,
+        quote_escape_character=None,
+        record_delimiter=None,
+    ):
         super().__init__(compression_type)
         self._allow_quoted_record_delimiter = allow_quoted_record_delimiter
         self._comments = comments
         self._field_delimiter = field_delimiter
-        if (
-                file_header_info is not None and
-                file_header_info not in [
-                    FILE_HEADER_INFO_USE,
-                    FILE_HEADER_INFO_IGNORE,
-                    FILE_HEADER_INFO_NONE,
-                ]
-        ):
+        if file_header_info is not None and file_header_info not in [
+            FILE_HEADER_INFO_USE,
+            FILE_HEADER_INFO_IGNORE,
+            FILE_HEADER_INFO_NONE,
+        ]:
             raise ValueError(
                 "file header info must be {0}, {1} or {2}".format(
                     FILE_HEADER_INFO_USE,
@@ -141,13 +141,14 @@ class JSONInputSerialization(InputSerialization):
 
     def __init__(self, compression_type=None, json_type=None):
         super().__init__(compression_type)
-        if (
-                json_type is not None and
-                json_type not in [JSON_TYPE_DOCUMENT, JSON_TYPE_LINES]
-        ):
+        if json_type is not None and json_type not in [
+            JSON_TYPE_DOCUMENT,
+            JSON_TYPE_LINES,
+        ]:
             raise ValueError(
                 "json type must be {0} or {1}".format(
-                    JSON_TYPE_DOCUMENT, JSON_TYPE_LINES,
+                    JSON_TYPE_DOCUMENT,
+                    JSON_TYPE_LINES,
                 ),
             )
         self._json_type = json_type
@@ -175,21 +176,25 @@ def toxml(self, element):
 class CSVOutputSerialization:
     """CSV output serialization."""
 
-    def __init__(self, field_delimiter=None, quote_character=None,
-                 quote_escape_character=None, quote_fields=None,
-                 record_delimiter=None):
+    def __init__(
+        self,
+        field_delimiter=None,
+        quote_character=None,
+        quote_escape_character=None,
+        quote_fields=None,
+        record_delimiter=None,
+    ):
         self._field_delimiter = field_delimiter
         self._quote_character = quote_character
         self._quote_escape_character = quote_escape_character
-        if (
-                quote_fields is not None and
-                quote_fields not in [
-                    QUOTE_FIELDS_ALWAYS, QUOTE_FIELDS_ASNEEDED,
-                ]
-        ):
+        if quote_fields is not None and quote_fields not in [
+            QUOTE_FIELDS_ALWAYS,
+            QUOTE_FIELDS_ASNEEDED,
+        ]:
             raise ValueError(
                 "quote fields must be {0} or {1}".format(
-                    QUOTE_FIELDS_ALWAYS, QUOTE_FIELDS_ASNEEDED,
+                    QUOTE_FIELDS_ALWAYS,
+                    QUOTE_FIELDS_ASNEEDED,
                 ),
             )
         self._quote_fields = quote_fields
@@ -230,17 +235,23 @@ def toxml(self, element):
 class SelectRequest:
     """Select object content request."""
 
-    def __init__(self, expression, input_serialization, output_serialization,
-                 request_progress=False, scan_start_range=None,
-                 scan_end_range=None):
+    def __init__(
+        self,
+        expression,
+        input_serialization,
+        output_serialization,
+        request_progress=False,
+        scan_start_range=None,
+        scan_end_range=None,
+    ):
         self._expession = expression
         if not isinstance(
-                input_serialization,
-                (
-                    CSVInputSerialization,
-                    JSONInputSerialization,
-                    ParquetInputSerialization,
-                ),
+            input_serialization,
+            (
+                CSVInputSerialization,
+                JSONInputSerialization,
+                ParquetInputSerialization,
+            ),
         ):
             raise ValueError(
                 "input serialization must be CSVInputSerialization, "
@@ -248,8 +259,8 @@ def __init__(self, expression, input_serialization, output_serialization,
             )
         self._input_serialization = input_serialization
         if not isinstance(
-                output_serialization,
-                (CSVOutputSerialization, JSONOutputSerialization),
+            output_serialization,
+            (CSVOutputSerialization, JSONOutputSerialization),
         ):
             raise ValueError(
                 "output serialization must be CSVOutputSerialization or "
@@ -273,7 +284,9 @@ def toxml(self, element):
         )
         if self._request_progress:
             SubElement(
-                SubElement(element, "RequestProgress"), "Enabled", "true",
+                SubElement(element, "RequestProgress"),
+                "Enabled",
+                "true",
             )
         if self._scan_start_range or self._scan_end_range:
             tag = SubElement(element, "ScanRange")
@@ -299,7 +312,7 @@ def _int(data):
 
 def _crc32(data):
     """Wrapper to binascii.crc32()."""
-    return crc32(data) & 0xffffffff
+    return crc32(data) & 0xFFFFFFFF
 
 
 def _decode_header(data):
@@ -349,16 +362,17 @@ class SelectObjectReader:
     Minio.select_object_content() API.
     """
 
-    def __init__(self, response):
+    def __init__(self, response, session):
         self._response = response
+        self._session = session
         self._stats = None
         self._payload = None
 
     def __enter__(self):
         return self
 
-    def __exit__(self, exc_type, exc_value, exc_traceback):
-        return self.close()
+    async def __aexit__(self, exc_type, exc_value, exc_traceback):
+        return await self.close()
 
     def readable(self):  # pylint: disable=no-self-use
         """Return this is readable."""
@@ -368,10 +382,11 @@ def writeable(self):  # pylint: disable=no-self-use
         """Return this is not writeable."""
         return False
 
-    def close(self):
+    async def close(self):
         """Close response and release network resources."""
         self._response.close()
-        self._response.release()
+        await self._response.release()
+        await self._session.close()
 
     def stats(self):
         """Get stats information."""
@@ -386,7 +401,8 @@ async def _read(self):
         if _crc32(prelude) != _int(prelude_crc):
             raise IOError(
                 "prelude CRC mismatch; expected: {0}, got: {1}".format(
-                    _crc32(prelude), _int(prelude_crc),
+                    _crc32(prelude),
+                    _int(prelude_crc),
                 ),
             )
 
@@ -407,7 +423,8 @@ async def _read(self):
         if headers.get(":message-type") == "error":
             raise MinioException(
                 "{0}: {1}".format(
-                    headers.get(":error-code"), headers.get(":error-message"),
+                    headers.get(":error-code"),
+                    headers.get(":error-message"),
                 ),
             )
 
@@ -418,7 +435,7 @@ async def _read(self):
         if headers.get(":event-type") == "Cont" or payload_length < 1:
             return await self._read()
 
-        payload = data[header_length:header_length+payload_length]
+        payload = data[header_length : header_length + payload_length]
         if headers.get(":event-type") in ["Progress", "Stats"]:
             self._stats = Stats(payload)
             return await self._read()
@@ -431,7 +448,7 @@ async def _read(self):
             "unknown event-type {0}".format(headers.get(":event-type")),
         )
 
-    async def stream(self, num_bytes=32*1024):
+    async def stream(self, num_bytes=32 * 1024):
         """
         Stream extracted payload from response data. Upon completion, caller
         should call self.close() to release network resources.
@@ -441,7 +458,8 @@ async def stream(self, num_bytes=32*1024):
                 result = self._payload
                 if num_bytes < len(self._payload):
                     result = self._payload[:num_bytes]
-                self._payload = self._payload[len(result):]
+                self._payload = self._payload[len(result) :]
                 yield result
             if await self._read() <= 0:
+                await self.close()
                 break
diff --git a/miniopy_async/signer.py b/miniopy_async/signer.py
index d6cacde..684fa27 100644
--- a/miniopy_async/signer.py
+++ b/miniopy_async/signer.py
@@ -43,7 +43,7 @@
 from . import time
 from .helpers import queryencode, sha256_hash
 
-SIGN_V4_ALGORITHM = 'AWS4-HMAC-SHA256'
+SIGN_V4_ALGORITHM = "AWS4-HMAC-SHA256"
 _MULTI_SPACE_REGEX = re.compile(r"( +)")
 
 
@@ -58,7 +58,9 @@ def _get_scope(date, region, service_name):
     """Get scope string."""
 
     return "{0}/{1}/{2}/aws4_request".format(
-        time.to_signer_date(date), region, service_name,
+        time.to_signer_date(date),
+        region,
+        service_name,
     )
 
 
@@ -69,21 +71,20 @@ def _get_canonical_headers(headers):
     for key, values in headers.items():
         key = key.lower()
         if key not in (
-                "authorization", "content-type",
-                "content-length", "user-agent",
+            "authorization",
+            "content-type",
+            "content-length",
+            "user-agent",
         ):
             values = values if isinstance(values, (list, tuple)) else [values]
-            canonical_headers[key] = ",".join([
-                _MULTI_SPACE_REGEX.sub(" ", value) for value in values
-            ])
+            canonical_headers[key] = ",".join(
+                [_MULTI_SPACE_REGEX.sub(" ", value) for value in values]
+            )
 
     canonical_headers = OrderedDict(sorted(canonical_headers.items()))
     signed_headers = ";".join(canonical_headers.keys())
     canonical_headers = "\n".join(
-        [
-            "{0}:{1}".format(key, value)
-            for key, value in canonical_headers.items()
-        ],
+        ["{0}:{1}".format(key, value) for key, value in canonical_headers.items()],
     )
     return canonical_headers, signed_headers
 
@@ -94,7 +95,8 @@ def _get_canonical_query_string(query):
     query = query or ""
     return "&".join(
         [
-            "=".join(pair) for pair in sorted(
+            "=".join(pair)
+            for pair in sorted(
                 [params.split("=") for params in query.split("&")],
             )
         ],
@@ -135,12 +137,10 @@ def _get_canonical_request_hash(method, url, headers, content_sha256):
 def _get_string_to_sign(date, scope, canonical_request_hash):
     """Get string-to-sign."""
 
-    return (
-        "AWS4-HMAC-SHA256\n{date}\n{scope}\n{canonical_request_hash}".format(
-            date=time.to_amz_date(date),
-            scope=scope,
-            canonical_request_hash=canonical_request_hash,
-        )
+    return "AWS4-HMAC-SHA256\n{date}\n{scope}\n{canonical_request_hash}".format(
+        date=time.to_amz_date(date),
+        scope=scope,
+        canonical_request_hash=canonical_request_hash,
     )
 
 
@@ -153,7 +153,8 @@ def _get_signing_key(secret_key, date, region, service_name):
     )
     date_region_key = _hmac_hash(date_key, region.encode())
     date_region_service_key = _hmac_hash(
-        date_region_key, service_name.encode(),
+        date_region_key,
+        service_name.encode(),
     )
     return _hmac_hash(date_region_service_key, b"aws4_request")
 
@@ -179,41 +180,50 @@ def _get_authorization(access_key, scope, signed_headers, signature):
 
 
 def _sign_v4(
-        service_name,
-        method,
-        url,
-        region,
-        headers,
-        credentials,
-        content_sha256,
-        date,
+    service_name,
+    method,
+    url,
+    region,
+    headers,
+    credentials,
+    content_sha256,
+    date,
 ):
     """Do signature V4 of given request for given service name."""
 
     scope = _get_scope(date, region, service_name)
     canonical_request_hash, signed_headers = _get_canonical_request_hash(
-        method, url, headers, content_sha256,
+        method,
+        url,
+        headers,
+        content_sha256,
     )
     string_to_sign = _get_string_to_sign(date, scope, canonical_request_hash)
     signing_key = _get_signing_key(
-        credentials.secret_key, date, region, service_name,
+        credentials.secret_key,
+        date,
+        region,
+        service_name,
     )
     signature = _get_signature(signing_key, string_to_sign)
     authorization = _get_authorization(
-        credentials.access_key, scope, signed_headers, signature,
+        credentials.access_key,
+        scope,
+        signed_headers,
+        signature,
     )
     headers["Authorization"] = authorization
     return headers
 
 
 def sign_v4_s3(
-        method,
-        url,
-        region,
-        headers,
-        credentials,
-        content_sha256,
-        date,
+    method,
+    url,
+    region,
+    headers,
+    credentials,
+    content_sha256,
+    date,
 ):
     """Do signature V4 of given request for S3 service."""
     return _sign_v4(
@@ -229,13 +239,13 @@ def sign_v4_s3(
 
 
 def sign_v4_sts(
-        method,
-        url,
-        region,
-        headers,
-        credentials,
-        content_sha256,
-        date,
+    method,
+    url,
+    region,
+    headers,
+    credentials,
+    content_sha256,
+    date,
 ):
     """Do signature V4 of given request for STS service."""
     return _sign_v4(
@@ -251,13 +261,18 @@ def sign_v4_sts(
 
 
 def _get_presign_canonical_request_hash(  # pylint: disable=invalid-name
-        method, url, access_key, scope, date, expires,
+    method,
+    url,
+    access_key,
+    scope,
+    date,
+    expires,
 ):
     """Get canonical request hash for presign request."""
 
     canonical_headers, signed_headers = "host:" + url.netloc, "host"
 
-    query = url.query+"&" if url.query else ""
+    query = url.query + "&" if url.query else ""
     query += (
         "X-Amz-Algorithm=AWS4-HMAC-SHA256"
         "&X-Amz-Credential={0}"
@@ -302,18 +317,23 @@ def _get_presign_canonical_request_hash(  # pylint: disable=invalid-name
 
 
 def presign_v4(
-        method,
-        url,
-        region,
-        credentials,
-        date,
-        expires,
+    method,
+    url,
+    region,
+    credentials,
+    date,
+    expires,
 ):
     """Do signature V4 of given presign request."""
 
     scope = _get_scope(date, region, "s3")
     canonical_request_hash, url = _get_presign_canonical_request_hash(
-        method, url, credentials.access_key, scope, date, expires,
+        method,
+        url,
+        credentials.access_key,
+        scope,
+        date,
+        expires,
     )
     string_to_sign = _get_string_to_sign(date, scope, canonical_request_hash)
     signing_key = _get_signing_key(credentials.secret_key, date, region, "s3")
diff --git a/miniopy_async/sse.py b/miniopy_async/sse.py
index 2c120e8..0a20ecb 100644
--- a/miniopy_async/sse.py
+++ b/miniopy_async/sse.py
@@ -41,6 +41,7 @@
 
 class Sse:
     """Server-side encryption base class."""
+
     __metaclass__ = ABCMeta
 
     @abstractmethod
@@ -57,7 +58,7 @@ def copy_headers(self):  # pylint: disable=no-self-use
 
 
 class SseCustomerKey(Sse):
-    """ Server-side encryption - customer key type."""
+    """Server-side encryption - customer key type."""
 
     def __init__(self, key):
         if len(key) != 32:
@@ -74,11 +75,9 @@ def __init__(self, key):
             "X-Amz-Server-Side-Encryption-Customer-Key-MD5": md5key,
         }
         self._copy_headers = {
-            "X-Amz-Copy-Source-Server-Side-Encryption-Customer-Algorithm":
-            "AES256",
+            "X-Amz-Copy-Source-Server-Side-Encryption-Customer-Algorithm": "AES256",
             "X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key": b64key,
-            "X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key-MD5":
-            md5key,
+            "X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key-MD5": md5key,
         }
 
     def headers(self):
@@ -94,13 +93,13 @@ class SseKMS(Sse):
     def __init__(self, key, context):
         self._headers = {
             "X-Amz-Server-Side-Encryption-Aws-Kms-Key-Id": key,
-            "X-Amz-Server-Side-Encryption": "aws:kms"
+            "X-Amz-Server-Side-Encryption": "aws:kms",
         }
         if context:
             data = bytes(json.dumps(context), "utf-8")
-            self._headers["X-Amz-Server-Side-Encryption-Context"] = (
-                base64.b64encode(data).decode()
-            )
+            self._headers["X-Amz-Server-Side-Encryption-Context"] = base64.b64encode(
+                data
+            ).decode()
 
     def headers(self):
         return self._headers.copy()
@@ -110,9 +109,7 @@ class SseS3(Sse):
     """Server-side encryption - S3 type."""
 
     def headers(self):
-        return {
-            "X-Amz-Server-Side-Encryption": "AES256"
-        }
+        return {"X-Amz-Server-Side-Encryption": "AES256"}
 
     def tls_required(self):
         return False
diff --git a/miniopy_async/sseconfig.py b/miniopy_async/sseconfig.py
index 6afd0ef..8603c00 100644
--- a/miniopy_async/sseconfig.py
+++ b/miniopy_async/sseconfig.py
@@ -29,7 +29,8 @@
 
 
 class Rule:
-    """Server-side encryption rule. """
+    """Server-side encryption rule."""
+
     __metaclass__ = ABCMeta
 
     def __init__(self, sse_algorithm, kms_master_key_id=None):
diff --git a/miniopy_async/tagging.py b/miniopy_async/tagging.py
index 7589e66..903e3da 100644
--- a/miniopy_async/tagging.py
+++ b/miniopy_async/tagging.py
@@ -39,10 +39,7 @@ def tags(self):
     def fromxml(cls, element):
         """Create new object with values from XML element."""
         element = find(element, "TagSet")
-        tags = (
-            None if find(element, "Tag") is None
-            else Tags.fromxml(element)
-        )
+        tags = None if find(element, "Tag") is None else Tags.fromxml(element)
         return cls(tags)
 
     def toxml(self, element):
diff --git a/miniopy_async/time.py b/miniopy_async/time.py
index 96ca7b5..7ceabff 100644
--- a/miniopy_async/time.py
+++ b/miniopy_async/time.py
@@ -43,8 +43,7 @@ def _set_locale(name):
 def _to_utc(value):
     """Convert to UTC time if value is not naive."""
     return (
-        value.astimezone(timezone.utc).replace(tzinfo=None)
-        if value.tzinfo else value
+        value.astimezone(timezone.utc).replace(tzinfo=None) if value.tzinfo else value
     )
 
 
@@ -66,16 +65,15 @@ def to_iso8601utc(value):
         return None
 
     value = _to_utc(value)
-    return (
-        value.strftime("%Y-%m-%dT%H:%M:%S.") + value.strftime("%f")[:3] + "Z"
-    )
+    return value.strftime("%Y-%m-%dT%H:%M:%S.") + value.strftime("%f")[:3] + "Z"
 
 
 def from_http_header(value):
     """Parse HTTP header date formatted string to datetime."""
     with _set_locale("C"):
         return datetime.strptime(
-            value, _HTTP_HEADER_FORMAT,
+            value,
+            _HTTP_HEADER_FORMAT,
         ).replace(tzinfo=timezone.utc)
 
 
diff --git a/miniopy_async/xml.py b/miniopy_async/xml.py
index 85b9dee..b6d92e7 100644
--- a/miniopy_async/xml.py
+++ b/miniopy_async/xml.py
@@ -28,7 +28,7 @@
 
 def Element(tag, namespace=_S3_NAMESPACE):  # pylint: disable=invalid-name
     """Create ElementTree.Element with tag and namespace."""
-    return ET.Element(tag, {'xmlns': namespace} if namespace else {})
+    return ET.Element(tag, {"xmlns": namespace} if namespace else {})
 
 
 def SubElement(parent, tag, text=None):  # pylint: disable=invalid-name
@@ -91,7 +91,9 @@ def getbytes(element):
     """Convert ElementTree.Element to bytes."""
     data = io.BytesIO()
     ET.ElementTree(element).write(
-        data, encoding=None, xml_declaration=False,
+        data,
+        encoding=None,
+        xml_declaration=False,
     )
     return data.getvalue()
 
diff --git a/setup.py b/setup.py
index 145ea4a..f3006a6 100644
--- a/setup.py
+++ b/setup.py
@@ -63,5 +63,5 @@
     long_description=readme,
     package_data={"": ["LICENSE", "README.md"]},
     include_package_data=True,
-    python_requires='>3.6',
+    python_requires=">3.6",
 )


Test patch:
diff --git a/tests.py b/tests.py
new file mode 100644
index 0000000..40e9ea9
--- /dev/null
+++ b/tests.py
@@ -0,0 +1,360 @@
+from miniopy_async import Minio
+from miniopy_async.commonconfig import (
+    ComposeSource,
+    CopySource,
+    ENABLED,
+    Filter,
+    Tags,
+)
+from miniopy_async.lifecycleconfig import Expiration, LifecycleConfig, Rule as lcRule
+from miniopy_async.versioningconfig import VersioningConfig
+from miniopy_async.sseconfig import Rule as sseRule, SSEConfig
+from miniopy_async.datatypes import PostPolicy
+from miniopy_async.deleteobjects import DeleteObject
+from miniopy_async.select import (
+    CSVInputSerialization,
+    CSVOutputSerialization,
+    SelectRequest,
+)
+from aiostream.stream import list as alist
+import asyncio
+import os
+import json
+from datetime import datetime, timedelta
+import traceback
+
+client = Minio(
+    "play.min.io",
+    access_key="Q3AM3UQ867SPQQA43P2F",
+    secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
+    secure=True,  # http for False, https for True
+)
+
+bucket_name = "my-bucket"
+test_file_name = ["testfile-1", "testfile-2"]
+
+error_func_list = []
+
+
+async def create_bucket():
+    try:
+        if not await client.bucket_exists(bucket_name):
+            await client.make_bucket(bucket_name)
+        print("Pass")
+    except:
+        traceback.print_exc()
+        error_func_list.append("create_bucket")
+
+
+async def put_object():
+    try:
+        test_content = b"1" * 1024 * 1024 * 5  # 5MB
+        for file_name in test_file_name:
+            with open(file_name, "wb") as file:
+                file.write(test_content)
+            await client.fput_object(bucket_name, file_name, file_name)
+            os.remove(file_name)
+        print("Pass")
+    except:
+        traceback.print_exc()
+        error_func_list.append("put_object")
+
+
+async def compose_object():
+    try:
+        sources = [
+            ComposeSource(bucket_name, file_name) for file_name in test_file_name
+        ]
+        await client.compose_object(bucket_name, "composed-object", sources)
+        print("Pass")
+    except:
+        traceback.print_exc()
+        error_func_list.append("compose_object")
+
+
+async def copy_object():
+    try:
+        await client.copy_object(
+            bucket_name,
+            "copied-object",
+            CopySource(bucket_name, test_file_name[0]),
+        )
+        print("Pass")
+    except:
+        traceback.print_exc()
+        error_func_list.append("copy_object")
+
+
+async def set_bucket_versioning():
+    try:
+        await client.set_bucket_versioning(bucket_name, VersioningConfig(ENABLED))
+        print("Pass")
+    except:
+        traceback.print_exc()
+        error_func_list.append("set_bucket_versioning")
+
+
+async def set_bucket_encryption():
+    try:
+        await client.set_bucket_encryption(
+            bucket_name,
+            SSEConfig(sseRule.new_sse_s3_rule()),
+        )
+        print("Pass")
+    except:
+        traceback.print_exc()
+        error_func_list.append("set_bucket_encryption")
+
+
+async def set_bucket_lifecycle():
+    try:
+        lifecycle_config = LifecycleConfig(
+            [
+                lcRule(
+                    ENABLED,
+                    rule_filter=Filter(prefix="logs/"),
+                    rule_id="rule2",
+                    expiration=Expiration(days=365),
+                ),
+            ],
+        )
+        await client.set_bucket_lifecycle(bucket_name, lifecycle_config)
+        print("Pass")
+    except:
+        traceback.print_exc()
+        error_func_list.append("set_bucket_lifecycle")
+
+
+async def set_bucket_policy():
+    try:
+        bucket_policy = {
+            "Version": "2012-10-17",
+            "Statement": [
+                {
+                    "Effect": "Allow",
+                    "Principal": {"AWS": "*"},
+                    "Action": ["s3:GetBucketLocation", "s3:ListBucket"],
+                    "Resource": "arn:aws:s3:::%s" % bucket_name,
+                },
+                {
+                    "Effect": "Allow",
+                    "Principal": {"AWS": "*"},
+                    "Action": "s3:GetObject",
+                    "Resource": "arn:aws:s3:::%s/*" % bucket_name,
+                },
+            ],
+        }
+        await client.set_bucket_policy(bucket_name, json.dumps(bucket_policy))
+        print("Pass")
+    except:
+        traceback.print_exc()
+        error_func_list.append("set_bucket_policy")
+
+
+async def set_bucket_tags():
+    try:
+        bucket_tags = Tags.new_bucket_tags()
+        bucket_tags["Project"] = "Project One"
+        bucket_tags["User"] = "jsmith"
+        await client.set_bucket_tags(bucket_name, bucket_tags)
+        print("Pass")
+    except:
+        traceback.print_exc()
+        error_func_list.append("set_bucket_tags")
+
+
+async def set_object_tags():
+    try:
+        object_tags = Tags.new_object_tags()
+        object_tags["Project"] = "Project One"
+        object_tags["User"] = "jsmith"
+        await client.set_object_tags(bucket_name, test_file_name[0], object_tags)
+        print("Pass")
+    except:
+        traceback.print_exc()
+        error_func_list.append("set_object_tags")
+
+
+async def stat_object():
+    try:
+        await client.stat_object(bucket_name, test_file_name[0])
+        print("Pass")
+    except:
+        traceback.print_exc()
+        error_func_list.append("stat_object")
+
+
+async def presigned_get_object():
+    try:
+        await client.presigned_get_object(bucket_name, test_file_name[0])
+        print("Pass")
+    except:
+        traceback.print_exc()
+        error_func_list.append("presigned_get_object")
+
+
+async def presigned_put_object():
+    try:
+        await client.presigned_put_object(bucket_name, test_file_name[0])
+        print("Pass")
+    except:
+        traceback.print_exc()
+        error_func_list.append("presigned_put_object")
+
+
+async def presigned_post_policy():
+    try:
+        bucket_post_policy = PostPolicy(
+            "my-bucket",
+            datetime.utcnow() + timedelta(days=10),
+        )
+        bucket_post_policy.add_starts_with_condition("key", "my/object/prefix/")
+        bucket_post_policy.add_content_length_range_condition(
+            1 * 1024 * 1024, 10 * 1024 * 1024
+        )
+        await client.presigned_post_policy(bucket_post_policy)
+        print("Pass")
+    except:
+        traceback.print_exc()
+        error_func_list.append("presigned_post_policy")
+
+
+async def list_buckets():
+    try:
+        await client.list_buckets()
+        print("Pass")
+    except:
+        traceback.print_exc()
+        error_func_list.append("list_buckets")
+
+
+async def list_objects():
+    try:
+        await client.list_objects(bucket_name)
+        print("Pass")
+    except:
+        traceback.print_exc()
+        error_func_list.append("list_objects")
+
+
+async def get_object():
+    try:
+        await client.fget_object(bucket_name, test_file_name[0], "testfile")
+        os.remove("testfile")
+        print("Pass")
+    except:
+        traceback.print_exc()
+        error_func_list.append("get_object")
+
+
+async def select_object_content():
+    try:
+        test_content = b"1" * 1024 * 512
+        file_name = "testfile-3"
+        with open(file_name, "wb") as file:
+            file.write(test_content)
+        await client.fput_object(bucket_name, file_name, file_name)
+        os.remove(file_name)
+        result = await client.select_object_content(
+            bucket_name,
+            file_name,
+            SelectRequest(
+                "select * from s3object",
+                CSVInputSerialization(),
+                CSVOutputSerialization(),
+                request_progress=True,
+            ),
+        )
+        for data in await alist(result.stream()):
+            data.decode()
+    except:
+        traceback.print_exc()
+        error_func_list.append("select_object_content")
+
+
+async def remove_object():
+    try:
+        await client.remove_object(bucket_name, test_file_name[0])
+        print("Pass")
+    except:
+        traceback.print_exc()
+        error_func_list.append("remove_object")
+
+
+async def remove_objects():
+    try:
+        objs = await client.list_objects(bucket_name, include_version=True)
+        await client.remove_objects(
+            bucket_name,
+            [DeleteObject(obj.object_name, obj.version_id) for obj in objs],
+        )
+        print("Pass")
+    except:
+        traceback.print_exc()
+        error_func_list.append("remove_objects")
+
+
+async def remove_bucket():
+    try:
+        await client.remove_bucket(bucket_name)
+        print("Pass")
+    except:
+        traceback.print_exc()
+        error_func_list.append("remove_bucket")
+
+
+async def main():
+    print("Testing create bucket...")
+    await create_bucket()
+    print("Testing put object...")
+    await put_object()
+    print("Testing compose object..")
+    await compose_object()
+    print("Testing copy object...")
+    await copy_object()
+    print("Testing set bucket versioning...")
+    await set_bucket_versioning()
+    print("Testing set bucket encryption...")
+    await set_bucket_encryption()
+    print("Testing set bucket lifecycle...")
+    await set_bucket_lifecycle()
+    print("Testing set bucket policy...")
+    await set_bucket_policy()
+    print("Testing set bucket tags...")
+    await set_bucket_tags()
+    print("Testing set object tags...")
+    await set_object_tags()
+    print("Testing stat object...")
+    await stat_object()
+    print("Testing presigned get object...")
+    await presigned_get_object()
+    print("Testing presigned put object...")
+    await presigned_put_object()
+    print("Testing presigned post policy...")
+    await presigned_post_policy()
+    print("Testing list bucket...")
+    await list_buckets()
+    print("Testing list objects...")
+    await list_objects()
+    print("Testing get object...")
+    await get_object()
+    print("Testing select object content...")
+    await select_object_content()
+    print("Testing remove object...")
+    await remove_object()
+    print("Testing remove objects...")
+    await remove_objects()
+    print("Testing remove bucket...")
+    await remove_bucket()
+
+
+loop = asyncio.get_event_loop()
+loop.run_until_complete(main())
+loop.close()
+
+if len(error_func_list) == 0:
+    print("\nAll Pass")
+else:
+    print("\nError Functions:")
+    for error_func in error_func_list:
+        print(error_func)
diff --git a/tests/__init__.py b/tests/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/tests/unit/__init__.py b/tests/unit/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/tests/unit/aio_utils_test.py b/tests/unit/aio_utils_test.py
deleted file mode 100644
index 88a2926..0000000
--- a/tests/unit/aio_utils_test.py
+++ /dev/null
@@ -1,31 +0,0 @@
-import asyncio
-
-import aiohttp
-from aiohttp import web
-from aiohttp.test_utils import AioHTTPTestCase
-
-from miniopy_async.api import _attach_finalizer
-
-
-class AioUtilsTest(AioHTTPTestCase):
-
-    async def get_application(self):
-        async def mock_get(request):
-            return web.Response(body=b''.join(bytes(i) for i in range(10240)))
-
-        app = web.Application()
-        app.router.add_get('/mock-get', mock_get)
-        return app
-
-    async def testClientSessionFinalizers(self):
-        session = aiohttp.ClientSession()
-        response = await session.get(self.client.make_url('/mock-get'))
-        connector = session.connector
-
-        _attach_finalizer(response, session, self.loop)
-        response.close()  # Can also call `response.read()`. This is needed to GC the response object
-        self.assertFalse(connector.closed)
-        del response, session
-        await asyncio.sleep(1)
-
-        self.assertTrue(connector.closed)