fix: lint

This commit is contained in:
Vlad Stan
2026-03-25 10:49:52 +02:00
parent 42039070b9
commit 1df9fa831d
11 changed files with 106 additions and 65 deletions
+3 -1
View File
@@ -85,7 +85,9 @@ async def test_asset_api_upload_list_update_and_delete(
assert deleted.status_code == 200
assert deleted.json()["success"] is True
missing = await client.get(f"/api/v1/assets/{asset['id']}", headers=user_headers_from)
missing = await client.get(
f"/api/v1/assets/{asset['id']}", headers=user_headers_from
)
assert missing.status_code == 404
+2 -4
View File
@@ -6,9 +6,9 @@ from fastapi.responses import RedirectResponse
from httpx import AsyncClient
from lnbits.core.crud.users import get_account, update_account
from lnbits.core.views.auth_api import get_account_by_email
from lnbits.core.models.users import Account
from lnbits.core.services.users import create_user_account
from lnbits.core.views.auth_api import get_account_by_email
from lnbits.settings import Settings
@@ -59,9 +59,7 @@ async def test_auth_api_logout_and_update_ui_customization(
@pytest.mark.anyio
async def test_auth_api_sso_login_and_callback(
http_client: AsyncClient, mocker
):
async def test_auth_api_sso_login_and_callback(http_client: AsyncClient, mocker):
user = await create_user_account(
Account(
id=uuid4().hex,
+3 -1
View File
@@ -163,7 +163,9 @@ async def test_callback_api_handles_subscription_flows_and_validation(mocker):
)
assert create_fiat_invoice_mock.await_count == 2
with pytest.raises(ValueError, match="PayPal subscription event missing custom metadata."):
with pytest.raises(
ValueError, match="PayPal subscription event missing custom metadata."
):
await handle_paypal_event(
{
"id": "evt_bad_sale",
+13 -5
View File
@@ -220,7 +220,9 @@ async def test_extension_api_pay_to_enable_and_catalog_views(mocker, admin_user)
await create_installed_extension(
_installable_extension(
ext_id,
pay_to_enable=PayToEnableInfo(required=True, amount=10, wallet=admin_wallet.id),
pay_to_enable=PayToEnableInfo(
required=True, amount=10, wallet=admin_wallet.id
),
)
)
@@ -410,6 +412,10 @@ async def test_extension_api_activate_uninstall_install_invoice_and_cleanup(mock
@pytest.mark.anyio
async def test_extension_api_review_endpoints(mocker):
ext_id = f"review_{uuid4().hex[:8]}"
reviews_base = "https://demo.lnbits.com/paidreviews/api/v1/AdFzLjzuKFLsdk4Bcnff6r"
tags_url = f"{reviews_base}/tags"
reviews_url = f"{reviews_base}/reviews/{ext_id}?offset=0&limit=5"
create_review_url = f"{reviews_base}/reviews"
request = Request(
{
"type": "http",
@@ -421,10 +427,10 @@ async def test_extension_api_review_endpoints(mocker):
)
mock_client = _MockHTTPClient(
{
"https://demo.lnbits.com/paidreviews/api/v1/AdFzLjzuKFLsdk4Bcnff6r/tags": _MockHTTPResponse(
tags_url: _MockHTTPResponse(
json_data=[{"tag": "good", "avg_rating": 900, "review_count": 3}]
),
f"https://demo.lnbits.com/paidreviews/api/v1/AdFzLjzuKFLsdk4Bcnff6r/reviews/{ext_id}?offset=0&limit=5": _MockHTTPResponse(
reviews_url: _MockHTTPResponse(
json_data={
"data": [
{
@@ -438,7 +444,7 @@ async def test_extension_api_review_endpoints(mocker):
"total": 1,
}
),
"https://demo.lnbits.com/paidreviews/api/v1/AdFzLjzuKFLsdk4Bcnff6r/reviews": _MockHTTPResponse(
create_review_url: _MockHTTPResponse(
json_data={
"payment_hash": f"hash_{uuid4().hex[:8]}",
"payment_request": "lnbc1review",
@@ -446,7 +452,9 @@ async def test_extension_api_review_endpoints(mocker):
),
}
)
mocker.patch("lnbits.core.views.extension_api.httpx.AsyncClient", return_value=mock_client)
mocker.patch(
"lnbits.core.views.extension_api.httpx.AsyncClient", return_value=mock_client
)
tags = await get_extension_reviews_tags()
assert tags[0].tag == "good"
+3 -2
View File
@@ -7,7 +7,6 @@ from lnbits.core.crud.extensions import create_user_extension, get_user_extensio
from lnbits.core.crud.users import get_account
from lnbits.core.models.extensions import (
Extension,
ExtensionMeta,
ExtensionRelease,
UserExtension,
)
@@ -81,7 +80,9 @@ async def test_extensions_builder_api_build_preview_and_cleanup(
"lnbits.core.views.extensions_builder_api.build_extension_from_data",
mocker.AsyncMock(return_value=(_release(ext_id), build_dir)),
)
clean_mock = mocker.patch("lnbits.core.views.extensions_builder_api.clean_extension_builder_data")
clean_mock = mocker.patch(
"lnbits.core.views.extensions_builder_api.clean_extension_builder_data"
)
try:
settings.lnbits_data_folder = str(tmp_path)
+3 -4
View File
@@ -1,5 +1,3 @@
from typing import Any
import pytest
from httpx import AsyncClient
from pytest_mock.plugin import MockerFixture
@@ -9,8 +7,8 @@ from lnbits.fiat.base import FiatSubscriptionResponse
class FakeStripeWallet:
def __init__(self, secret: str | None = "secret"):
self._secret = secret
def __init__(self, secret: str | None = None):
self._secret = secret if secret is not None else "connection-token"
async def create_terminal_connection_token(self) -> dict[str, str]:
if self._secret is None:
@@ -77,6 +75,7 @@ async def test_fiat_api_test_provider_and_subscription_lifecycle(
assert created.status_code == 200
assert created.json()["checkout_session_url"] == "https://stripe.example/checkout"
provider.create_subscription.assert_awaited_once()
assert provider.create_subscription.await_args is not None
assert provider.create_subscription.await_args.args[2].wallet_id == from_wallet.id
cancelled = await client.delete(
+12 -4
View File
@@ -20,13 +20,13 @@ from lnbits.core.models import Account, CreateInvoice
from lnbits.core.models.lnurl import CreateLnurlPayment, LnurlScan
from lnbits.core.models.wallets import KeyType, WalletTypeInfo
from lnbits.core.services.payments import create_wallet_invoice
from lnbits.core.services.users import create_user_account
from lnbits.core.views.lnurl_api import (
api_lnurlscan,
api_lnurlscan_post,
api_payments_pay_lnurl,
api_perform_lnurlauth,
)
from lnbits.core.services.users import create_user_account
TEST_BOLT11 = (
"lnbc1pnsu5z3pp57getmdaxhg5kc9yh2a2qsh7cjf4gnccgkw0qenm8vsqv50w7s"
@@ -57,9 +57,13 @@ async def test_lnurl_api_scan_routes_validate_and_forward(mocker):
)
scanned = await api_lnurlscan("lnurl1example")
assert isinstance(scanned, LnurlPayResponse)
assert scanned.callback == pay_response.callback
scanned_post = await api_lnurlscan_post(scan=LnurlScan(lnurl=LnAddress("alice@example.com")))
scanned_post = await api_lnurlscan_post(
scan=LnurlScan(lnurl=LnAddress("alice@example.com"))
)
assert isinstance(scanned_post, LnurlPayResponse)
assert scanned_post.callback == pay_response.callback
mocker.patch(
@@ -102,6 +106,7 @@ async def test_lnurl_api_auth_and_pay_flow(mocker):
mocker.AsyncMock(return_value=auth_response),
)
authenticated = await api_perform_lnurlauth(auth_response, wallet_info)
assert isinstance(authenticated, LnurlAuthResponse)
assert authenticated.k1 == "k1-value"
mocker.patch(
@@ -114,7 +119,7 @@ async def test_lnurl_api_auth_and_pay_flow(mocker):
action_response = LnurlPayActionResponse(
pr=LightningInvoice(TEST_BOLT11),
disposable=False,
successAction=MessageAction(message="paid"),
successAction=parse_obj_as(MessageAction, {"message": "paid"}),
)
fetch_mock = mocker.patch(
"lnbits.core.views.lnurl_api.fetch_lnurl_pay_request",
@@ -126,13 +131,16 @@ async def test_lnurl_api_auth_and_pay_flow(mocker):
)
paid = await api_payments_pay_lnurl(
CreateLnurlPayment(res=pay_response, amount=2_000, unit="USD", comment="thanks"),
CreateLnurlPayment(
res=pay_response, amount=2_000, unit="USD", comment="thanks"
),
wallet_info,
)
assert paid.payment_hash == payment.payment_hash
fetch_mock.assert_awaited_once()
pay_mock.assert_awaited_once()
assert pay_mock.await_args is not None
assert action_response.successAction is not None
assert pay_mock.await_args.kwargs["extra"] == {
"stored": True,
"success_action": action_response.successAction.json(),
+54 -39
View File
@@ -1,9 +1,10 @@
from typing import Any
from collections.abc import Callable
from typing import Any, cast
from uuid import uuid4
import httpx
import pytest
from httpx import AsyncClient
from fastapi import HTTPException
from pytest_mock.plugin import MockerFixture
from lnbits.core.views import node_api
@@ -12,6 +13,8 @@ from lnbits.nodes.base import (
ChannelBalance,
ChannelPoint,
ChannelState,
ChannelStats,
Node,
NodeChannel,
NodeFees,
NodeInfoResponse,
@@ -46,13 +49,13 @@ class FakeNode:
color="#ffffff",
num_peers=1,
blockheight=1,
channel_stats={
"counts": {ChannelState.ACTIVE: 1},
"avg_size": 3000,
"biggest_size": 3000,
"smallest_size": 3000,
"total_capacity": 3000,
},
channel_stats=ChannelStats(
counts={ChannelState.ACTIVE: 1},
avg_size=3000,
biggest_size=3000,
smallest_size=3000,
total_capacity=3000,
),
addresses=["127.0.0.1:9735"],
onchain_balance_sat=1,
onchain_confirmed_sat=1,
@@ -146,8 +149,20 @@ class FakeNode:
return "fake-node-id"
class FakeFundingSource:
def __init__(
self,
features: list[Feature],
node_factory: Callable[[Any], Any] | None,
):
self.features = features
self.__node_cls__ = node_factory
class MockHTTPResponse:
def __init__(self, json_data: dict[str, Any], status_error: Exception | None = None):
def __init__(
self, json_data: dict[str, Any], status_error: Exception | None = None
):
self._json_data = json_data
self._status_error = status_error
@@ -181,26 +196,24 @@ async def test_node_api_dependency_guards(settings: Settings, mocker: MockerFixt
original_public = settings.lnbits_public_node_ui
try:
settings.lnbits_node_ui = True
funding_source = type("FundingSource", (), {})()
funding_source.features = []
funding_source.__node_cls__ = None
funding_source = FakeFundingSource([], None)
mocker.patch(
"lnbits.core.views.node_api.get_funding_source",
return_value=funding_source,
)
with pytest.raises(Exception) as excinfo:
with pytest.raises(HTTPException) as excinfo:
node_api.require_node()
assert excinfo.value.status_code == 501
node_enabled_source = type("FundingSource", (), {})()
node_enabled_source.features = [Feature.nodemanager]
node_enabled_source.__node_cls__ = lambda wallet: "fake-node"
node_enabled_source = FakeFundingSource(
[Feature.nodemanager], lambda wallet: "fake-node"
)
mocker.patch(
"lnbits.core.views.node_api.get_funding_source",
return_value=node_enabled_source,
)
settings.lnbits_node_ui = False
with pytest.raises(Exception) as disabled:
with pytest.raises(HTTPException) as disabled:
node_api.require_node()
assert disabled.value.status_code == 503
@@ -208,7 +221,7 @@ async def test_node_api_dependency_guards(settings: Settings, mocker: MockerFixt
assert node_api.require_node() == "fake-node"
settings.lnbits_public_node_ui = False
with pytest.raises(Exception) as public_disabled:
with pytest.raises(HTTPException) as public_disabled:
node_api.check_public()
assert public_disabled.value.status_code == 503
finally:
@@ -222,6 +235,7 @@ async def test_node_api_route_functions_with_fake_node(
mocker: MockerFixture,
):
fake_node = FakeNode()
node = cast(Node, fake_node)
original_transactions = settings.lnbits_node_ui_transactions
settings.lnbits_node_ui_transactions = True
rank_response = MockHTTPResponse(
@@ -243,23 +257,23 @@ async def test_node_api_route_functions_with_fake_node(
try:
assert await node_api.api_get_ok() is None
public_info = await node_api.api_get_public_info(node=fake_node)
public_info = await node_api.api_get_public_info(node=node)
assert public_info.backend_name == "FakeNode"
info = await node_api.api_get_info(node=fake_node)
info = await node_api.api_get_info(node=node)
assert info is not None
assert info.id == "node-id"
channels = await node_api.api_get_channels(node=fake_node)
channels = await node_api.api_get_channels(node=node)
assert channels is not None
assert channels[0].id == "chan-1"
channel = await node_api.api_get_channel("chan-1", node=fake_node)
channel = await node_api.api_get_channel("chan-1", node=node)
assert channel is not None
assert channel.peer_id == "peer-1"
created = await node_api.api_create_channel(
node=fake_node,
node=node,
peer_id="peer-1",
funding_amount=10_000,
push_amount=100,
@@ -272,41 +286,41 @@ async def test_node_api_route_functions_with_fake_node(
funding_txid=None,
output_index=None,
force=True,
node=fake_node,
node=node,
)
assert deleted is not None
assert deleted[0].id == "chan-1"
await node_api.api_set_channel_fees(
"chan-1",
node=fake_node,
node=node,
fee_ppm=42,
fee_base_msat=7,
)
assert fake_node.fees_updated == ("chan-1", 7, 42)
payments = await node_api.api_get_payments(node=fake_node, filters=Filters())
payments = await node_api.api_get_payments(node=node, filters=Filters())
assert payments is not None
assert payments.total == 1
invoices = await node_api.api_get_invoices(node=fake_node, filters=Filters())
invoices = await node_api.api_get_invoices(node=node, filters=Filters())
assert invoices is not None
assert invoices.total == 1
peers = await node_api.api_get_peers(node=fake_node)
peers = await node_api.api_get_peers(node=node)
assert peers[0].id == "peer-1"
connect = await node_api.api_connect_peer(
uri="peer-1@127.0.0.1:9735", node=fake_node
uri="peer-1@127.0.0.1:9735", node=node
)
assert connect["uri"] == "peer-1@127.0.0.1:9735"
disconnect = await node_api.api_disconnect_peer("peer-1", node=fake_node)
disconnect = await node_api.api_disconnect_peer("peer-1", node=node)
assert disconnect["peer_id"] == "peer-1"
rank = await node_api.api_get_1ml_stats(node=fake_node)
rank = await node_api.api_get_1ml_stats(node=node)
assert rank is not None
assert rank["channelcount"] == 2
assert rank.channelcount == 2
finally:
settings.lnbits_node_ui_transactions = original_transactions
@@ -317,6 +331,7 @@ async def test_node_api_transactions_and_rank_errors(
mocker: MockerFixture,
):
fake_node = FakeNode()
node = cast(Node, fake_node)
original_transactions = settings.lnbits_node_ui_transactions
settings.lnbits_node_ui_transactions = False
@@ -334,16 +349,16 @@ async def test_node_api_transactions_and_rank_errors(
)
try:
with pytest.raises(Exception) as payments:
await node_api.api_get_payments(node=fake_node, filters=Filters())
with pytest.raises(HTTPException) as payments:
await node_api.api_get_payments(node=node, filters=Filters())
assert payments.value.status_code == 503
with pytest.raises(Exception) as invoices:
await node_api.api_get_invoices(node=fake_node, filters=Filters())
with pytest.raises(HTTPException) as invoices:
await node_api.api_get_invoices(node=node, filters=Filters())
assert invoices.value.status_code == 503
with pytest.raises(Exception) as rank:
await node_api.api_get_1ml_stats(node=fake_node)
with pytest.raises(HTTPException) as rank:
await node_api.api_get_1ml_stats(node=node)
assert rank.value.status_code == 404
assert rank.value.detail == "Node not found on 1ml.com"
finally:
+1 -1
View File
@@ -11,6 +11,7 @@ from lnbits.core.models.payments import CancelInvoice, CreatePayment, SettleInvo
from lnbits.core.models.users import AccountId
from lnbits.core.models.wallets import KeyType, WalletTypeInfo
from lnbits.core.services.payments import create_wallet_invoice
from lnbits.core.services.users import create_user_account
from lnbits.core.views.payment_api import (
api_all_payments_paginated,
api_payments_cancel,
@@ -20,7 +21,6 @@ from lnbits.core.views.payment_api import (
api_payments_settle,
api_payments_wallets_stats,
)
from lnbits.core.services.users import create_user_account
from lnbits.db import Filters
from lnbits.wallets.base import InvoiceResponse
+3 -1
View File
@@ -96,5 +96,7 @@ async def test_user_api_create_wallet_validates_currency():
with pytest.raises(ValueError, match="Currency 'INVALID' not allowed."):
await api_users_create_user_wallet(user.id, name="invalid", currency="INVALID")
wallet = await api_users_create_user_wallet(user.id, name="eur wallet", currency="EUR")
wallet = await api_users_create_user_wallet(
user.id, name="eur wallet", currency="EUR"
)
assert wallet.currency == "EUR"
+9 -3
View File
@@ -13,7 +13,9 @@ def _admin_headers(adminkey: str) -> dict[str, str]:
@pytest.mark.anyio
async def test_wallet_api_share_invite_reject_accept_and_delete(http_client: AsyncClient):
async def test_wallet_api_share_invite_reject_accept_and_delete(
http_client: AsyncClient,
):
owner = await create_user_account(
Account(
id=uuid4().hex,
@@ -129,7 +131,9 @@ async def test_wallet_api_paginated_update_reset_and_store_paylinks(
assert renamed.json()["name"] == "renamed-wallet"
original_admin_key = extra_wallet.adminkey
reset = await http_client.put(f"/api/v1/wallet/reset/{extra_wallet.id}?usr={user.id}")
reset = await http_client.put(
f"/api/v1/wallet/reset/{extra_wallet.id}?usr={user.id}"
)
assert reset.status_code == 200
assert reset.json()["adminkey"] != original_admin_key
@@ -181,4 +185,6 @@ async def test_wallet_api_shared_wallet_requires_source_id(http_client: AsyncCli
json={"wallet_type": "lightning-shared"},
)
assert response.status_code == 400
assert response.json()["detail"] == "Shared wallet ID is required for shared wallets."
assert (
response.json()["detail"] == "Shared wallet ID is required for shared wallets."
)