From f0a66e41fb4ce2724bb10a07c2b7580c4a64913e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?dni=20=E2=9A=A1?= <office@dnilabs.com>
Date: Wed, 16 Aug 2023 12:22:14 +0200
Subject: [PATCH] [CHORE] flake8 issues E402, E721 and F821 (#1874)

* F821: undefine name
disabled and logged webhook_listener for opennode and lnpay because they are obviously not working
* E402: module level import not at top of file
* E721 fixes, only popped up for python3.9 not 3.10
---
 .flake8                             |  3 +-
 lnbits/core/views/api.py            |  2 +-
 lnbits/db.py                        |  2 +-
 lnbits/server.py                    |  9 ++-
 lnbits/settings.py                  |  2 +-
 lnbits/tasks.py                     |  4 +-
 lnbits/wallets/lndgrpc.py           | 29 +++++-----
 lnbits/wallets/lnpay.py             | 44 +++++++-------
 lnbits/wallets/macaroon/macaroon.py |  2 +-
 lnbits/wallets/opennode.py          | 27 +++++----
 poetry.lock                         | 90 ++++++++++++++---------------
 tests/core/test_db.py               |  2 +-
 tests/core/views/test_api.py        |  4 +-
 13 files changed, 108 insertions(+), 112 deletions(-)

diff --git a/.flake8 b/.flake8
index d34970308..4d79d9768 100644
--- a/.flake8
+++ b/.flake8
@@ -3,8 +3,9 @@ max-line-length = 150
 exclude = lnbits/wallets/lnd_grpc_files/, lnbits/extensions/
 ignore =
     # E203 whitespace before ':' black does not like it
-    E203
+    E203,
     # E402: module level import not at top of file
+    # needed for https://github.com/lnbits/lnbits/pull/1876
     E402,
     # W503: line break before binary operator
     W503,
diff --git a/lnbits/core/views/api.py b/lnbits/core/views/api.py
index 323a17ed0..245803d87 100644
--- a/lnbits/core/views/api.py
+++ b/lnbits/core/views/api.py
@@ -468,7 +468,7 @@ async def api_payments_sse(
 async def api_payment(payment_hash, X_Api_Key: Optional[str] = Header(None)):
     # We use X_Api_Key here because we want this call to work with and without keys
     # If a valid key is given, we also return the field "details", otherwise not
-    wallet = await get_wallet_for_key(X_Api_Key) if type(X_Api_Key) == str else None  # type: ignore
+    wallet = await get_wallet_for_key(X_Api_Key) if isinstance(X_Api_Key, str) else None  # type: ignore
 
     # we have to specify the wallet id here, because postgres and sqlite return internal payments in different order
     # and get_standalone_payment otherwise just fetches the first one, causing unpredictable results
diff --git a/lnbits/db.py b/lnbits/db.py
index 714513f78..7dc0baba1 100644
--- a/lnbits/db.py
+++ b/lnbits/db.py
@@ -462,7 +462,7 @@ class Filters(BaseModel, Generic[TFilterModel]):
         if self.search and self.model:
             if DB_TYPE == POSTGRES:
                 where_stmts.append(
-                    f"lower(concat({f', '.join(self.model.__search_fields__)})) LIKE ?"
+                    f"lower(concat({', '.join(self.model.__search_fields__)})) LIKE ?"
                 )
             elif DB_TYPE == SQLITE:
                 where_stmts.append(
diff --git a/lnbits/server.py b/lnbits/server.py
index 787ddc5e4..c000d4dd5 100644
--- a/lnbits/server.py
+++ b/lnbits/server.py
@@ -1,17 +1,16 @@
-import uvloop
-from uvicorn.supervisors import ChangeReload
-
-uvloop.install()
-
 import multiprocessing as mp
 import time
 from pathlib import Path
 
 import click
 import uvicorn
+import uvloop
+from uvicorn.supervisors import ChangeReload
 
 from lnbits.settings import set_cli_settings, settings
 
+uvloop.install()
+
 
 @click.command(
     context_settings=dict(
diff --git a/lnbits/settings.py b/lnbits/settings.py
index 6de31e721..9975cf6ed 100644
--- a/lnbits/settings.py
+++ b/lnbits/settings.py
@@ -26,7 +26,7 @@ def list_parse_fallback(v):
 class LNbitsSettings(BaseSettings):
     @classmethod
     def validate(cls, val):
-        if type(val) == str:
+        if isinstance(val, str):
             val = val.split(",") if val else []
         return val
 
diff --git a/lnbits/tasks.py b/lnbits/tasks.py
index c123d7538..c6e97e709 100644
--- a/lnbits/tasks.py
+++ b/lnbits/tasks.py
@@ -46,8 +46,8 @@ class SseListenersDict(dict):
         self.name = name or f"sse_listener_{str(uuid.uuid4())[:8]}"
 
     def __setitem__(self, key, value):
-        assert type(key) == str, f"{key} is not a string"
-        assert type(value) == asyncio.Queue, f"{value} is not an asyncio.Queue"
+        assert isinstance(key, str), f"{key} is not a string"
+        assert isinstance(value, asyncio.Queue), f"{value} is not an asyncio.Queue"
         logger.trace(f"sse: adding listener {key} to {self.name}. len = {len(self)+1}")
         return super().__setitem__(key, value)
 
diff --git a/lnbits/wallets/lndgrpc.py b/lnbits/wallets/lndgrpc.py
index b471370c8..0cbe7dde8 100644
--- a/lnbits/wallets/lndgrpc.py
+++ b/lnbits/wallets/lndgrpc.py
@@ -1,10 +1,3 @@
-imports_ok = True
-try:
-    import grpc
-    from grpc import RpcError
-except ImportError:  # pragma: nocover
-    imports_ok = False
-
 import asyncio
 import base64
 import hashlib
@@ -13,14 +6,6 @@ from typing import AsyncGenerator, Dict, Optional
 
 from loguru import logger
 
-from .macaroon import AESCipher, load_macaroon
-
-if imports_ok:
-    import lnbits.wallets.lnd_grpc_files.lightning_pb2 as ln
-    import lnbits.wallets.lnd_grpc_files.lightning_pb2_grpc as lnrpc
-    import lnbits.wallets.lnd_grpc_files.router_pb2 as router
-    import lnbits.wallets.lnd_grpc_files.router_pb2_grpc as routerrpc
-
 from lnbits.settings import settings
 
 from .base import (
@@ -30,6 +15,20 @@ from .base import (
     StatusResponse,
     Wallet,
 )
+from .macaroon import AESCipher, load_macaroon
+
+imports_ok = True
+try:
+    import grpc
+    from grpc import RpcError
+except ImportError:  # pragma: nocover
+    imports_ok = False
+
+if imports_ok:
+    import lnbits.wallets.lnd_grpc_files.lightning_pb2 as ln
+    import lnbits.wallets.lnd_grpc_files.lightning_pb2_grpc as lnrpc
+    import lnbits.wallets.lnd_grpc_files.router_pb2 as router
+    import lnbits.wallets.lnd_grpc_files.router_pb2_grpc as routerrpc
 
 
 def get_ssl_context(cert_path: str):
diff --git a/lnbits/wallets/lnpay.py b/lnbits/wallets/lnpay.py
index 0f2ad1914..919af8f78 100644
--- a/lnbits/wallets/lnpay.py
+++ b/lnbits/wallets/lnpay.py
@@ -1,11 +1,8 @@
 import asyncio
 import hashlib
-import json
-from http import HTTPStatus
 from typing import AsyncGenerator, Dict, Optional
 
 import httpx
-from fastapi import HTTPException
 from loguru import logger
 
 from lnbits.settings import settings
@@ -65,7 +62,7 @@ class LNPayWallet(Wallet):
         memo: Optional[str] = None,
         description_hash: Optional[bytes] = None,
         unhashed_description: Optional[bytes] = None,
-        **kwargs,
+        **_,
     ) -> InvoiceResponse:
         data: Dict = {"num_satoshis": f"{amount}"}
         if description_hash:
@@ -139,25 +136,26 @@ class LNPayWallet(Wallet):
             yield value
 
     async def webhook_listener(self):
+        logger.error("LNPay webhook listener disabled.")
+        return
         # TODO: request.get_data is undefined, was it something with Flask or quart?
         # probably issue introduced when refactoring?
-        text: str = await request.get_data()  # type: ignore
-        try:
-            data = json.loads(text)
-        except json.decoder.JSONDecodeError:
-            logger.error(f"got something wrong on lnpay webhook endpoint: {text[:200]}")
-            data = None
-        if (
-            type(data) is not dict
-            or "event" not in data
-            or data["event"].get("name") != "wallet_receive"
-        ):
-            raise HTTPException(status_code=HTTPStatus.NO_CONTENT)
+        # text: str = await request.get_data()
+        # try:
+        #     data = json.loads(text)
+        # except json.decoder.JSONDecodeError:
+        #     logger.error(f"error on lnpay webhook endpoint: {text[:200]}")
+        #     data = None
+        # if (
+        #     type(data) is not dict
+        #     or "event" not in data
+        #     or data["event"].get("name") != "wallet_receive"
+        # ):
+        #     raise HTTPException(status_code=HTTPStatus.NO_CONTENT)
 
-        lntx_id = data["data"]["wtx"]["lnTx"]["id"]
-        r = await self.client.get(f"/lntx/{lntx_id}?fields=settled")
-        data = r.json()
-        if data["settled"]:
-            await self.queue.put(lntx_id)
-
-        raise HTTPException(status_code=HTTPStatus.NO_CONTENT)
+        # lntx_id = data["data"]["wtx"]["lnTx"]["id"]
+        # r = await self.client.get(f"/lntx/{lntx_id}?fields=settled")
+        # data = r.json()
+        # if data["settled"]:
+        #     await self.queue.put(lntx_id)
+        # raise HTTPException(status_code=HTTPStatus.NO_CONTENT)
diff --git a/lnbits/wallets/macaroon/macaroon.py b/lnbits/wallets/macaroon/macaroon.py
index ca75303e1..c27602a52 100644
--- a/lnbits/wallets/macaroon/macaroon.py
+++ b/lnbits/wallets/macaroon/macaroon.py
@@ -52,7 +52,7 @@ class AESCipher:
         return data + (chr(length) * length).encode()
 
     def unpad(self, data):
-        return data[: -(data[-1] if type(data[-1]) == int else ord(data[-1]))]
+        return data[: -(data[-1] if isinstance(data[-1], int) else ord(data[-1]))]
 
     @property
     def passphrase(self):
diff --git a/lnbits/wallets/opennode.py b/lnbits/wallets/opennode.py
index 8053da882..b922a3358 100644
--- a/lnbits/wallets/opennode.py
+++ b/lnbits/wallets/opennode.py
@@ -1,10 +1,7 @@
 import asyncio
-import hmac
-from http import HTTPStatus
 from typing import AsyncGenerator, Optional
 
 import httpx
-from fastapi import HTTPException
 from loguru import logger
 
 from lnbits.settings import settings
@@ -136,18 +133,20 @@ class OpenNodeWallet(Wallet):
             yield value
 
     async def webhook_listener(self):
+        logger.error("webhook listener for opennode is disabled.")
+        return
         # TODO: request.form is undefined, was it something with Flask or quart?
         # probably issue introduced when refactoring?
-        data = await request.form  # type: ignore
-        if "status" not in data or data["status"] != "paid":
-            raise HTTPException(status_code=HTTPStatus.NO_CONTENT)
+        # data = await request.form  # type: ignore
+        # if "status" not in data or data["status"] != "paid":
+        #     raise HTTPException(status_code=HTTPStatus.NO_CONTENT)
 
-        charge_id = data["id"]
-        x = hmac.new(self.auth["Authorization"].encode("ascii"), digestmod="sha256")
-        x.update(charge_id.encode("ascii"))
-        if x.hexdigest() != data["hashed_order"]:
-            logger.error("invalid webhook, not from opennode")
-            raise HTTPException(status_code=HTTPStatus.NO_CONTENT)
+        # charge_id = data["id"]
+        # x = hmac.new(self.auth["Authorization"].encode("ascii"), digestmod="sha256")
+        # x.update(charge_id.encode("ascii"))
+        # if x.hexdigest() != data["hashed_order"]:
+        #     logger.error("invalid webhook, not from opennode")
+        #     raise HTTPException(status_code=HTTPStatus.NO_CONTENT)
 
-        await self.queue.put(charge_id)
-        raise HTTPException(status_code=HTTPStatus.NO_CONTENT)
+        # await self.queue.put(charge_id)
+        # raise HTTPException(status_code=HTTPStatus.NO_CONTENT)
diff --git a/poetry.lock b/poetry.lock
index eeeba3706..0bbcbc870 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -543,13 +543,13 @@ dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "sphinx (<2)", "tox"]
 
 [[package]]
 name = "dill"
-version = "0.3.6"
-description = "serialize all of python"
+version = "0.3.7"
+description = "serialize all of Python"
 optional = false
 python-versions = ">=3.7"
 files = [
-    {file = "dill-0.3.6-py3-none-any.whl", hash = "sha256:a07ffd2351b8c678dfc4a856a3005f8067aea51d6ba6c700796a4d9e280f39f0"},
-    {file = "dill-0.3.6.tar.gz", hash = "sha256:e5db55f3687856d8fbdab002ed78544e1c4559a130302693d839dfe8f93f2373"},
+    {file = "dill-0.3.7-py3-none-any.whl", hash = "sha256:76b122c08ef4ce2eedcd4d1abd8e641114bfc6c2867f49f3c41facf65bf19f5e"},
+    {file = "dill-0.3.7.tar.gz", hash = "sha256:cc1c8b182eb3013e24bd475ff2e9295af86c1a38eb1aff128dac8962a9ce3c03"},
 ]
 
 [package.extras]
@@ -667,19 +667,19 @@ testing = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "diff-cover (>=7.5)", "p
 
 [[package]]
 name = "flake8"
-version = "6.0.0"
+version = "6.1.0"
 description = "the modular source code checker: pep8 pyflakes and co"
 optional = false
 python-versions = ">=3.8.1"
 files = [
-    {file = "flake8-6.0.0-py2.py3-none-any.whl", hash = "sha256:3833794e27ff64ea4e9cf5d410082a8b97ff1a06c16aa3d2027339cd0f1195c7"},
-    {file = "flake8-6.0.0.tar.gz", hash = "sha256:c61007e76655af75e6785a931f452915b371dc48f56efd765247c8fe68f2b181"},
+    {file = "flake8-6.1.0-py2.py3-none-any.whl", hash = "sha256:ffdfce58ea94c6580c77888a86506937f9a1a227dfcd15f245d694ae20a6b6e5"},
+    {file = "flake8-6.1.0.tar.gz", hash = "sha256:d5b3857f07c030bdb5bf41c7f53799571d75c4491748a3adcd47de929e34cd23"},
 ]
 
 [package.dependencies]
 mccabe = ">=0.7.0,<0.8.0"
-pycodestyle = ">=2.10.0,<2.11.0"
-pyflakes = ">=3.0.0,<3.1.0"
+pycodestyle = ">=2.11.0,<2.12.0"
+pyflakes = ">=3.1.0,<3.2.0"
 
 [[package]]
 name = "grpcio"
@@ -795,13 +795,13 @@ socks = ["socksio (==1.*)"]
 
 [[package]]
 name = "identify"
-version = "2.5.25"
+version = "2.5.26"
 description = "File identification library for Python"
 optional = false
 python-versions = ">=3.8"
 files = [
-    {file = "identify-2.5.25-py2.py3-none-any.whl", hash = "sha256:9df2489842707d431b38ce3410ef8df40da5b10a3e28a3fcac1a42523e956409"},
-    {file = "identify-2.5.25.tar.gz", hash = "sha256:db4de0e758c0db8f81996816cd2f3f2f8c5c8d49a7fd02f3b4109aac6fd80e29"},
+    {file = "identify-2.5.26-py2.py3-none-any.whl", hash = "sha256:c22a8ead0d4ca11f1edd6c9418c3220669b3b7533ada0a0ffa6cc0ef85cf9b54"},
+    {file = "identify-2.5.26.tar.gz", hash = "sha256:7243800bce2f58404ed41b7c002e53d4d22bcf3ae1b7900c2d7aefd95394bf7f"},
 ]
 
 [package.extras]
@@ -839,13 +839,13 @@ testing = ["flake8 (<5)", "flufl.flake8", "importlib-resources (>=1.3)", "packag
 
 [[package]]
 name = "importlib-resources"
-version = "6.0.0"
+version = "6.0.1"
 description = "Read resources from Python packages"
 optional = false
 python-versions = ">=3.8"
 files = [
-    {file = "importlib_resources-6.0.0-py3-none-any.whl", hash = "sha256:d952faee11004c045f785bb5636e8f885bed30dc3c940d5d42798a2a4541c185"},
-    {file = "importlib_resources-6.0.0.tar.gz", hash = "sha256:4cf94875a8368bd89531a756df9a9ebe1f150e0f885030b461237bc7f2d905f2"},
+    {file = "importlib_resources-6.0.1-py3-none-any.whl", hash = "sha256:134832a506243891221b88b4ae1213327eea96ceb4e407a00d790bb0626f45cf"},
+    {file = "importlib_resources-6.0.1.tar.gz", hash = "sha256:4359457e42708462b9626a04657c6208ad799ceb41e5c58c57ffa0e6a098a5d4"},
 ]
 
 [package.dependencies]
@@ -1290,29 +1290,29 @@ files = [
 
 [[package]]
 name = "pathspec"
-version = "0.11.1"
+version = "0.11.2"
 description = "Utility library for gitignore style pattern matching of file paths."
 optional = false
 python-versions = ">=3.7"
 files = [
-    {file = "pathspec-0.11.1-py3-none-any.whl", hash = "sha256:d8af70af76652554bd134c22b3e8a1cc46ed7d91edcdd721ef1a0c51a84a5293"},
-    {file = "pathspec-0.11.1.tar.gz", hash = "sha256:2798de800fa92780e33acca925945e9a19a133b715067cf165b8866c15a31687"},
+    {file = "pathspec-0.11.2-py3-none-any.whl", hash = "sha256:1d6ed233af05e679efb96b1851550ea95bbb64b7c490b0f5aa52996c11e92a20"},
+    {file = "pathspec-0.11.2.tar.gz", hash = "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3"},
 ]
 
 [[package]]
 name = "platformdirs"
-version = "3.9.1"
+version = "3.10.0"
 description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
 optional = false
 python-versions = ">=3.7"
 files = [
-    {file = "platformdirs-3.9.1-py3-none-any.whl", hash = "sha256:ad8291ae0ae5072f66c16945166cb11c63394c7a3ad1b1bc9828ca3162da8c2f"},
-    {file = "platformdirs-3.9.1.tar.gz", hash = "sha256:1b42b450ad933e981d56e59f1b97495428c9bd60698baab9f3eb3d00d5822421"},
+    {file = "platformdirs-3.10.0-py3-none-any.whl", hash = "sha256:d7c24979f292f916dc9cbf8648319032f551ea8c49a4c9bf2fb556a02070ec1d"},
+    {file = "platformdirs-3.10.0.tar.gz", hash = "sha256:b45696dab2d7cc691a3226759c0d3b00c47c8b6e293d96f6436f733303f77f6d"},
 ]
 
 [package.extras]
-docs = ["furo (>=2023.5.20)", "proselint (>=0.13)", "sphinx (>=7.0.1)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"]
-test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.3.1)", "pytest-cov (>=4.1)", "pytest-mock (>=3.10)"]
+docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.1)", "sphinx-autodoc-typehints (>=1.24)"]
+test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)"]
 
 [[package]]
 name = "pluggy"
@@ -1417,13 +1417,13 @@ files = [
 
 [[package]]
 name = "pycodestyle"
-version = "2.10.0"
+version = "2.11.0"
 description = "Python style guide checker"
 optional = false
-python-versions = ">=3.6"
+python-versions = ">=3.8"
 files = [
-    {file = "pycodestyle-2.10.0-py2.py3-none-any.whl", hash = "sha256:8a4eaf0d0495c7395bdab3589ac2db602797d76207242c17d470186815706610"},
-    {file = "pycodestyle-2.10.0.tar.gz", hash = "sha256:347187bdb476329d98f695c213d7295a846d1152ff4fe9bacb8a9590b8ee7053"},
+    {file = "pycodestyle-2.11.0-py2.py3-none-any.whl", hash = "sha256:5d1013ba8dc7895b548be5afb05740ca82454fd899971563d2ef625d090326f8"},
+    {file = "pycodestyle-2.11.0.tar.gz", hash = "sha256:259bcc17857d8a8b3b4a2327324b79e5f020a13c16074670f9c8c8f872ea76d0"},
 ]
 
 [[package]]
@@ -1526,28 +1526,28 @@ email = ["email-validator (>=1.0.3)"]
 
 [[package]]
 name = "pyflakes"
-version = "3.0.1"
+version = "3.1.0"
 description = "passive checker of Python programs"
 optional = false
-python-versions = ">=3.6"
+python-versions = ">=3.8"
 files = [
-    {file = "pyflakes-3.0.1-py2.py3-none-any.whl", hash = "sha256:ec55bf7fe21fff7f1ad2f7da62363d749e2a470500eab1b555334b67aa1ef8cf"},
-    {file = "pyflakes-3.0.1.tar.gz", hash = "sha256:ec8b276a6b60bd80defed25add7e439881c19e64850afd9b346283d4165fd0fd"},
+    {file = "pyflakes-3.1.0-py2.py3-none-any.whl", hash = "sha256:4132f6d49cb4dae6819e5379898f2b8cce3c5f23994194c24b77d5da2e36f774"},
+    {file = "pyflakes-3.1.0.tar.gz", hash = "sha256:a0aae034c444db0071aa077972ba4768d40c830d9539fd45bf4cd3f8f6992efc"},
 ]
 
 [[package]]
 name = "pylint"
-version = "2.17.4"
+version = "2.17.5"
 description = "python code static checker"
 optional = false
 python-versions = ">=3.7.2"
 files = [
-    {file = "pylint-2.17.4-py3-none-any.whl", hash = "sha256:7a1145fb08c251bdb5cca11739722ce64a63db479283d10ce718b2460e54123c"},
-    {file = "pylint-2.17.4.tar.gz", hash = "sha256:5dcf1d9e19f41f38e4e85d10f511e5b9c35e1aa74251bf95cdd8cb23584e2db1"},
+    {file = "pylint-2.17.5-py3-none-any.whl", hash = "sha256:73995fb8216d3bed149c8d51bba25b2c52a8251a2c8ac846ec668ce38fab5413"},
+    {file = "pylint-2.17.5.tar.gz", hash = "sha256:f7b601cbc06fef7e62a754e2b41294c2aa31f1cb659624b9a85bcba29eaf8252"},
 ]
 
 [package.dependencies]
-astroid = ">=2.15.4,<=2.17.0-dev0"
+astroid = ">=2.15.6,<=2.17.0-dev0"
 colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""}
 dill = [
     {version = ">=0.2", markers = "python_version < \"3.11\""},
@@ -2089,13 +2089,13 @@ files = [
 
 [[package]]
 name = "tomlkit"
-version = "0.11.8"
+version = "0.12.1"
 description = "Style preserving TOML library"
 optional = false
 python-versions = ">=3.7"
 files = [
-    {file = "tomlkit-0.11.8-py3-none-any.whl", hash = "sha256:8c726c4c202bdb148667835f68d68780b9a003a9ec34167b6c673b38eff2a171"},
-    {file = "tomlkit-0.11.8.tar.gz", hash = "sha256:9330fc7faa1db67b541b28e62018c17d20be733177d290a13b24c62d1614e0c3"},
+    {file = "tomlkit-0.12.1-py3-none-any.whl", hash = "sha256:712cbd236609acc6a3e2e97253dfc52d4c2082982a88f61b640ecf0817eab899"},
+    {file = "tomlkit-0.12.1.tar.gz", hash = "sha256:38e1ff8edb991273ec9f6181244a6a391ac30e9f5098e7535640ea6be97a7c86"},
 ]
 
 [[package]]
@@ -2197,23 +2197,23 @@ test = ["aiohttp", "flake8 (>=3.9.2,<3.10.0)", "mypy (>=0.800)", "psutil", "pyOp
 
 [[package]]
 name = "virtualenv"
-version = "20.24.1"
+version = "20.24.2"
 description = "Virtual Python Environment builder"
 optional = false
 python-versions = ">=3.7"
 files = [
-    {file = "virtualenv-20.24.1-py3-none-any.whl", hash = "sha256:01aacf8decd346cf9a865ae85c0cdc7f64c8caa07ff0d8b1dfc1733d10677442"},
-    {file = "virtualenv-20.24.1.tar.gz", hash = "sha256:2ef6a237c31629da6442b0bcaa3999748108c7166318d1f55cc9f8d7294e97bd"},
+    {file = "virtualenv-20.24.2-py3-none-any.whl", hash = "sha256:43a3052be36080548bdee0b42919c88072037d50d56c28bd3f853cbe92b953ff"},
+    {file = "virtualenv-20.24.2.tar.gz", hash = "sha256:fd8a78f46f6b99a67b7ec5cf73f92357891a7b3a40fd97637c27f854aae3b9e0"},
 ]
 
 [package.dependencies]
-distlib = ">=0.3.6,<1"
-filelock = ">=3.12,<4"
-platformdirs = ">=3.5.1,<4"
+distlib = ">=0.3.7,<1"
+filelock = ">=3.12.2,<4"
+platformdirs = ">=3.9.1,<4"
 
 [package.extras]
 docs = ["furo (>=2023.5.20)", "proselint (>=0.13)", "sphinx (>=7.0.1)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"]
-test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.3.1)", "pytest-env (>=0.8.1)", "pytest-freezer (>=0.4.6)", "pytest-mock (>=3.10)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=67.8)", "time-machine (>=2.9)"]
+test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8)", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10)"]
 
 [[package]]
 name = "websocket-client"
diff --git a/tests/core/test_db.py b/tests/core/test_db.py
index 8fd7b7849..eda537ed5 100644
--- a/tests/core/test_db.py
+++ b/tests/core/test_db.py
@@ -9,4 +9,4 @@ from lnbits.db import POSTGRES
 async def test_date_conversion(db):
     if db.type == POSTGRES:
         row = await db.fetchone("SELECT now()::date")
-        assert row and type(row[0]) == date
+        assert row and isinstance(row[0], date)
diff --git a/tests/core/views/test_api.py b/tests/core/views/test_api.py
index af5153ea6..12397db71 100644
--- a/tests/core/views/test_api.py
+++ b/tests/core/views/test_api.py
@@ -285,7 +285,7 @@ async def test_decode_invoice(client, invoice):
 async def test_api_payment_without_key(invoice):
     # check the payment status
     response = await api_payment(invoice["payment_hash"])
-    assert type(response) == dict
+    assert isinstance(response, dict)
     assert response["paid"] is True
     # no key, that's why no "details"
     assert "details" not in response
@@ -298,7 +298,7 @@ async def test_api_payment_with_key(invoice, inkey_headers_from):
     response = await api_payment(
         invoice["payment_hash"], inkey_headers_from["X-Api-Key"]
     )
-    assert type(response) == dict
+    assert isinstance(response, dict)
     assert response["paid"] is True
     assert "details" in response