From 9ddaf0c9fe06b44290c68294a0016400ca618fee Mon Sep 17 00:00:00 2001 From: michael1011 Date: Wed, 21 Aug 2024 02:26:39 +0200 Subject: [PATCH] test: gRPC integration tests --- .gitignore | 2 + Makefile | 25 +- src/database/helpers/invoice_helper.rs | 3 +- src/grpc/server.rs | 16 +- src/grpc/service.rs | 30 +++ src/main.rs | 1 + src/settler.rs | 4 +- tests/hold/__init__.py | 0 tests/hold/protos/__init__.py | 4 + tests/hold/test_grpc.py | 334 +++++++++++++++++++++++++ tests/{ => hold}/test_rpc.py | 8 +- tests/{ => hold}/utils.py | 22 +- tests/poetry.lock | 156 +++++++++++- tests/pyproject.toml | 13 +- 14 files changed, 594 insertions(+), 24 deletions(-) create mode 100644 tests/hold/__init__.py create mode 100644 tests/hold/protos/__init__.py create mode 100644 tests/hold/test_grpc.py rename tests/{ => hold}/test_rpc.py (96%) rename tests/{ => hold}/utils.py (84%) diff --git a/.gitignore b/.gitignore index cb4f54e..8ae67c1 100644 --- a/.gitignore +++ b/.gitignore @@ -16,4 +16,6 @@ target/ # option (not recommended) you can uncomment the following to ignore the entire idea folder. .idea/ +tests/hold/protos/* +!tests/hold/protos/__init__.py **/__pycache__ diff --git a/Makefile b/Makefile index 0b35eca..8247333 100644 --- a/Makefile +++ b/Makefile @@ -13,17 +13,28 @@ python-lint: python-format: cd tests && poetry run ruff format +python-protos: + cd tests && poetry run python -m grpc_tools.protoc -I ../protos \ + --python_out=hold/protos \ + --pyi_out=hold/protos \ + --grpc_python_out=hold/protos \ + ../protos/hold.proto + regtest-start: git submodule init git submodule update - chmod -R 777 regtest + chmod -R 777 regtest 2> /dev/null || true cd regtest && COMPOSE_PROFILES=ci ./start.sh - cd .. - mkdir regtest/data/cln1/plugins - cp target/debug/hold regtest/data/cln1/plugins/ - docker exec boltz-cln-1 lightning-cli --regtest plugin stop /root/hold.sh - rm -rf regtest/data/cln1/regtest/hold/ - docker exec boltz-cln-1 lightning-cli --regtest plugin start /root/.lightning/plugins/hold + mkdir regtest/data/cln2/plugins + cp target/debug/hold regtest/data/cln2/plugins/ + docker exec boltz-cln-2 lightning-cli --regtest plugin stop /root/hold.sh + rm -rf regtest/data/cln2/regtest/hold/ + docker exec boltz-cln-2 lightning-cli --regtest plugin start /root/.lightning/plugins/hold + + sleep 1 + docker exec boltz-cln-2 chmod 777 -R /root/.lightning/regtest/hold + + make python-protos regtest-stop: cd regtest && ./stop.sh diff --git a/src/database/helpers/invoice_helper.rs b/src/database/helpers/invoice_helper.rs index edfc313..f44edd9 100644 --- a/src/database/helpers/invoice_helper.rs +++ b/src/database/helpers/invoice_helper.rs @@ -76,6 +76,7 @@ impl InvoiceHelper for InvoiceHelperDatabase { let invoices = invoices::dsl::invoices .select(Invoice::as_select()) + .order_by(invoices::dsl::id) .load(&mut con)?; let htlcs = Htlc::belonging_to(&invoices) .select(Htlc::as_select()) @@ -95,7 +96,7 @@ impl InvoiceHelper for InvoiceHelperDatabase { let invoices = invoices::dsl::invoices .select(Invoice::as_select()) .filter(invoices::dsl::id.ge(index_start)) - .order_by(invoices::dsl::id.desc()) + .order_by(invoices::dsl::id) .limit(limit as i64) .load(&mut con)?; let htlcs = Htlc::belonging_to(&invoices) diff --git a/src/grpc/server.rs b/src/grpc/server.rs index 10006d1..5aa422a 100644 --- a/src/grpc/server.rs +++ b/src/grpc/server.rs @@ -15,6 +15,8 @@ use tonic::transport::ServerTlsConfig; pub struct Server { host: String, port: i64, + is_regtest: bool, + directory: PathBuf, cancellation_token: CancellationToken, @@ -28,9 +30,11 @@ where T: InvoiceHelper + Sync + Send + Clone + 'static, E: InvoiceEncoder + Sync + Send + Clone + 'static, { + #[allow(clippy::too_many_arguments)] pub fn new( host: &str, port: i64, + is_regtest: bool, cancellation_token: CancellationToken, directory: PathBuf, invoice_helper: T, @@ -42,6 +46,7 @@ where settler, encoder, directory, + is_regtest, invoice_helper, cancellation_token, host: host.to_string(), @@ -49,7 +54,15 @@ where } pub async fn start(&self) -> Result<()> { - let socket_addr = SocketAddr::new(IpAddr::from_str(self.host.as_str())?, self.port as u16); + // Always listen to all interfaces on regtest + let socket_addr = SocketAddr::new( + IpAddr::from_str(if !self.is_regtest { + self.host.as_str() + } else { + "0.0.0.0" + })?, + self.port as u16, + ); info!("Starting gRPC server on: {}", socket_addr); let (identity, ca) = load_certificates(self.directory.clone())?; @@ -201,6 +214,7 @@ mod test { let server = Server::new( "127.0.0.1", port, + false, token.clone(), certs_dir.clone(), make_mock_invoice_helper(), diff --git a/src/grpc/service.rs b/src/grpc/service.rs index b2f8df0..4d46548 100644 --- a/src/grpc/service.rs +++ b/src/grpc/service.rs @@ -206,6 +206,36 @@ where let mut state_rx = self.settler.state_rx(); + match self + .invoice_helper + .get_by_payment_hash(¶ms.payment_hash) + { + Ok(res) => { + if let Some(res) = res { + if let Ok(state) = InvoiceState::try_from(res.invoice.state.as_str()) { + if let Err(err) = tx + .send(Ok(TrackResponse { + state: transform_invoice_state(state), + })) + .await + { + error!("Could not send invoice state update: {}", err); + return Err(Status::new( + Code::Internal, + format!("could not send initial invoice state: {}", err), + )); + } + } + } + } + Err(err) => { + return Err(Status::new( + Code::Internal, + format!("could not fetch invoice state from database: {}", err), + )); + } + }; + tokio::spawn(async move { loop { match state_rx.recv().await { diff --git a/src/main.rs b/src/main.rs index cd314f2..05e1c39 100644 --- a/src/main.rs +++ b/src/main.rs @@ -163,6 +163,7 @@ async fn main() -> Result<()> { let grpc_server = grpc::server::Server::new( &grpc_host, grpc_port, + config.network == "regtest", cancellation_token.clone(), std::env::current_dir()?.join(utils::built_info::PKG_NAME), invoice_helper, diff --git a/src/settler.rs b/src/settler.rs index f87bdf0..321b87b 100644 --- a/src/settler.rs +++ b/src/settler.rs @@ -63,6 +63,8 @@ pub struct Settler { pending_htlcs: Arc, Vec>>>, } +// TODO: only allow valid state transitions + impl Settler where T: InvoiceHelper + Sync + Send + Clone, @@ -90,7 +92,7 @@ where self.invoice_helper .set_invoice_state(invoice.id, InvoiceState::Accepted)?; let _ = self.state_tx.send(StateUpdate { - state: InvoiceState::Paid, + state: InvoiceState::Accepted, bolt11: invoice.bolt11.clone(), payment_hash: invoice.payment_hash.clone(), }); diff --git a/tests/hold/__init__.py b/tests/hold/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/hold/protos/__init__.py b/tests/hold/protos/__init__.py new file mode 100644 index 0000000..1da1dcf --- /dev/null +++ b/tests/hold/protos/__init__.py @@ -0,0 +1,4 @@ +import sys +from pathlib import Path + +sys.path.insert(0, str(Path(__file__).parent)) diff --git a/tests/hold/test_grpc.py b/tests/hold/test_grpc.py new file mode 100644 index 0000000..0701bca --- /dev/null +++ b/tests/hold/test_grpc.py @@ -0,0 +1,334 @@ +from __future__ import annotations + +import concurrent.futures +import time +from pathlib import Path + +import grpc +import pytest + +from hold.protos.hold_pb2 import ( + CancelRequest, + GetInfoRequest, + GetInfoResponse, + Hop, + Invoice, + InvoiceRequest, + InvoiceResponse, + InvoiceState, + ListRequest, + ListResponse, + RoutingHint, + SettleRequest, + TrackRequest, +) +from hold.protos.hold_pb2_grpc import HoldStub +from hold.utils import LndPay, lightning, new_preimage_bytes, time_now + + +class TestGrpc: + @pytest.fixture(scope="class", autouse=True) + def cl(self) -> HoldStub: + cert_path = Path("../regtest/data/cln2/regtest/hold") + creds = grpc.ssl_channel_credentials( + root_certificates=cert_path.joinpath("ca.pem").read_bytes(), + private_key=cert_path.joinpath("client-key.pem").read_bytes(), + certificate_chain=cert_path.joinpath("client.pem").read_bytes(), + ) + channel = grpc.secure_channel( + "127.0.0.1:9738", + creds, + options=(("grpc.ssl_target_name_override", "hold"),), + ) + client = HoldStub(channel) + + yield client + + channel.close() + + def test_get_info(self, cl: HoldStub) -> None: + info: GetInfoResponse = cl.GetInfo(GetInfoRequest()) + assert info.version != "" + + def test_invoice_defaults(self, cl: HoldStub) -> None: + amount = 21_000 + (_, payment_hash) = new_preimage_bytes() + + invoice: InvoiceResponse = cl.Invoice( + InvoiceRequest(payment_hash=payment_hash, amount_msat=amount) + ) + decoded = lightning("decode", invoice.bolt11) + + assert decoded["currency"] == "bcrt" + assert decoded["created_at"] - int(time_now().timestamp()) < 2 + assert decoded["expiry"] == 3_600 + assert decoded["payee"] == lightning("getinfo")["id"] + assert decoded["amount_msat"] == amount + assert decoded["description"] == "" + assert decoded["min_final_cltv_expiry"] == 80 + assert "payment_secret" in decoded + assert decoded["features"] == "024100" + assert decoded["payment_hash"] == payment_hash.hex() + assert decoded["valid"] + + @pytest.mark.parametrize( + "memo", + [ + "some", + "text", + "Send to BTC address", + "some way longer text with so many chars", + ], + ) + def test_invoice_memo(self, cl: HoldStub, memo: str) -> None: + (_, payment_hash) = new_preimage_bytes() + invoice: InvoiceResponse = cl.Invoice( + InvoiceRequest(payment_hash=payment_hash, amount_msat=1, memo=memo) + ) + decoded = lightning("decode", invoice.bolt11) + + assert decoded["description"] == memo + + def test_invoice_description_hash(self, cl: HoldStub) -> None: + (preimage, payment_hash) = new_preimage_bytes() + invoice: InvoiceResponse = cl.Invoice( + InvoiceRequest(payment_hash=payment_hash, amount_msat=1, hash=preimage) + ) + decoded = lightning("decode", invoice.bolt11) + + assert decoded["description_hash"] == preimage.hex() + + @pytest.mark.parametrize( + "expiry", + [ + 1, + 2, + 3_600, + 7_200, + 10_000, + ], + ) + def test_invoice_expiry(self, cl: HoldStub, expiry: int) -> None: + (_, payment_hash) = new_preimage_bytes() + invoice: InvoiceResponse = cl.Invoice( + InvoiceRequest(payment_hash=payment_hash, amount_msat=1, expiry=expiry) + ) + decoded = lightning("decode", invoice.bolt11) + + assert decoded["expiry"] == expiry + + @pytest.mark.parametrize( + "expiry", + [ + 1, + 2, + 80, + 144, + 288, + ], + ) + def test_invoice_min_final_cltv_expiry(self, cl: HoldStub, expiry: int) -> None: + (_, payment_hash) = new_preimage_bytes() + invoice: InvoiceResponse = cl.Invoice( + InvoiceRequest( + payment_hash=payment_hash, amount_msat=1, min_final_cltv_expiry=expiry + ) + ) + decoded = lightning("decode", invoice.bolt11) + + assert decoded["min_final_cltv_expiry"] == expiry + + def test_invoice_routing_hints(self, cl: HoldStub) -> None: + (_, payment_hash) = new_preimage_bytes() + + hints = [ + RoutingHint( + hops=[ + Hop( + public_key=bytes.fromhex( + "026165850492521f4ac8abd9bd8088123446d126f648ca35e60f88177dc149ceb2" + ), + short_channel_id=123, + base_fee=1, + ppm_fee=2, + cltv_expiry_delta=23, + ), + Hop( + public_key=bytes.fromhex( + "02d96eadea3d780104449aca5c93461ce67c1564e2e1d73225fa67dd3b997a6018" + ), + short_channel_id=321, + base_fee=2, + ppm_fee=21, + cltv_expiry_delta=26, + ), + ] + ), + RoutingHint( + hops=[ + Hop( + public_key=bytes.fromhex( + "027a7666ec63448bacaec5b00398dd263522755e95bcded7b52b2c9dc4533d34f1" + ), + short_channel_id=121, + base_fee=1_000, + ppm_fee=2_500, + cltv_expiry_delta=80, + ) + ] + ), + ] + + invoice: InvoiceResponse = cl.Invoice( + InvoiceRequest( + payment_hash=payment_hash, + amount_msat=1, + routing_hints=hints, + ) + ) + decoded = lightning("decode", invoice.bolt11) + routes = decoded["routes"] + + assert len(routes) == 2 + + assert len(routes[0]) == 2 + assert len(routes[1]) == 1 + + for i in range(len(routes)): + for j in range(len(routes[i])): + decoded_hop = routes[i][j] + hint = hints[i].hops[j] + + assert decoded_hop["pubkey"] == hint.public_key.hex() + assert decoded_hop["short_channel_id"] == f"0x0x{hint.short_channel_id}" + assert decoded_hop["fee_base_msat"] == hint.base_fee + assert decoded_hop["fee_proportional_millionths"] == hint.ppm_fee + assert decoded_hop["cltv_expiry_delta"] == hint.cltv_expiry_delta + + def test_list_all(self, cl: HoldStub) -> None: + cl.Invoice(InvoiceRequest(payment_hash=new_preimage_bytes()[1], amount_msat=1)) + + hold_list: ListResponse = cl.List(ListRequest()) + assert len(hold_list.invoices) > 0 + + def test_list_payment_hash(self, cl: HoldStub) -> None: + (_, payment_hash) = new_preimage_bytes() + invoice: InvoiceResponse = cl.Invoice( + InvoiceRequest(payment_hash=payment_hash, amount_msat=1) + ) + + hold_list: ListResponse = cl.List(ListRequest(payment_hash=payment_hash)) + assert len(hold_list.invoices) == 1 + + assert hold_list.invoices[0].bolt11 == invoice.bolt11 + assert hold_list.invoices[0].payment_hash == payment_hash + + def test_list_payment_hash_not_found(self, cl: HoldStub) -> None: + (_, payment_hash) = new_preimage_bytes() + + hold_list: ListResponse = cl.List(ListRequest(payment_hash=payment_hash)) + assert len(hold_list.invoices) == 0 + + def test_list_pagination(self, cl: HoldStub) -> None: + for _ in range(10): + (_, payment_hash) = new_preimage_bytes() + cl.Invoice(InvoiceRequest(payment_hash=payment_hash, amount_msat=1)) + + page: ListResponse = cl.List( + ListRequest(pagination=ListRequest.Pagination(index_start=0, limit=2)) + ) + assert len(page.invoices) == 2 + assert page.invoices[0].id == 1 + assert page.invoices[1].id == 2 + + page: ListResponse = cl.List( + ListRequest(pagination=ListRequest.Pagination(index_start=2, limit=1)) + ) + assert len(page.invoices) == 1 + assert page.invoices[0].id == 2 + + page: ListResponse = cl.List( + ListRequest(pagination=ListRequest.Pagination(index_start=3, limit=5)) + ) + assert len(page.invoices) == 5 + assert page.invoices[0].id == 3 + + def test_track_settle(self, cl: HoldStub) -> None: + (preimage, payment_hash) = new_preimage_bytes() + invoice: InvoiceResponse = cl.Invoice( + InvoiceRequest(payment_hash=payment_hash, amount_msat=1_000) + ) + + def track_states() -> list[InvoiceState]: + return [ + update.state + for update in cl.Track(TrackRequest(payment_hash=payment_hash)) + ] + + with concurrent.futures.ThreadPoolExecutor() as pool: + fut = pool.submit(track_states) + + pay = LndPay(1, invoice.bolt11) + pay.start() + time.sleep(1) + + invoice_state: Invoice = cl.List( + ListRequest(payment_hash=payment_hash) + ).invoices[0] + assert invoice_state.state == InvoiceState.ACCEPTED + assert len(invoice_state.htlcs) == 1 + assert invoice_state.htlcs[0].state == InvoiceState.ACCEPTED + + cl.Settle(SettleRequest(payment_preimage=preimage)) + pay.join() + + assert fut.result() == [ + InvoiceState.UNPAID, + InvoiceState.ACCEPTED, + InvoiceState.PAID, + ] + + invoice_state = cl.List(ListRequest(payment_hash=payment_hash)).invoices[0] + assert invoice_state.state == InvoiceState.PAID + assert len(invoice_state.htlcs) == 1 + assert invoice_state.htlcs[0].state == InvoiceState.PAID + + def test_track_cancel(self, cl: HoldStub) -> None: + (_, payment_hash) = new_preimage_bytes() + invoice: InvoiceResponse = cl.Invoice( + InvoiceRequest(payment_hash=payment_hash, amount_msat=1_000) + ) + + def track_states() -> list[InvoiceState]: + return [ + update.state + for update in cl.Track(TrackRequest(payment_hash=payment_hash)) + ] + + with concurrent.futures.ThreadPoolExecutor() as pool: + fut = pool.submit(track_states) + + pay = LndPay(1, invoice.bolt11) + pay.start() + time.sleep(1) + + invoice_state: Invoice = cl.List( + ListRequest(payment_hash=payment_hash) + ).invoices[0] + assert invoice_state.state == InvoiceState.ACCEPTED + assert len(invoice_state.htlcs) == 1 + assert invoice_state.htlcs[0].state == InvoiceState.ACCEPTED + + cl.Cancel(CancelRequest(payment_hash=payment_hash)) + pay.join() + + assert fut.result() == [ + InvoiceState.UNPAID, + InvoiceState.ACCEPTED, + InvoiceState.CANCELLED, + ] + + invoice_state = cl.List(ListRequest(payment_hash=payment_hash)).invoices[0] + assert invoice_state.state == InvoiceState.CANCELLED + assert len(invoice_state.htlcs) == 1 + assert invoice_state.htlcs[0].state == InvoiceState.CANCELLED diff --git a/tests/test_rpc.py b/tests/hold/test_rpc.py similarity index 96% rename from tests/test_rpc.py rename to tests/hold/test_rpc.py index d5ed457..6201e2d 100644 --- a/tests/test_rpc.py +++ b/tests/hold/test_rpc.py @@ -3,7 +3,7 @@ import time from typing import Any -from utils import LndPay, lightning, new_preimage +from hold.utils import LndPay, lightning, new_preimage def check_unpaid_invoice( @@ -19,7 +19,7 @@ def check_unpaid_invoice( class TestRpc: def test_invoice(self) -> None: - amount = 2112 + amount = 2_112 (_, payment_hash) = new_preimage() invoice = lightning("holdinvoice", payment_hash, f"{amount}") @@ -67,7 +67,7 @@ def test_settle(self) -> None: payer = LndPay(1, invoice) payer.start() - time.sleep(2) + time.sleep(1) data = lightning("listholdinvoices", payment_hash)["holdinvoices"][0] assert data["state"] == "accepted" @@ -95,7 +95,7 @@ def test_cancel(self) -> None: payer = LndPay(1, invoice) payer.start() - time.sleep(2) + time.sleep(1) data = lightning("listholdinvoices", payment_hash)["holdinvoices"][0] assert data["state"] == "accepted" diff --git a/tests/utils.py b/tests/hold/utils.py similarity index 84% rename from tests/utils.py rename to tests/hold/utils.py index e742081..3857b1a 100644 --- a/tests/utils.py +++ b/tests/hold/utils.py @@ -2,12 +2,27 @@ import json import os +from datetime import datetime, timezone from hashlib import sha256 from threading import Thread from typing import Any -def lightning(*args: str, node: int = 1) -> dict[str, Any]: +def time_now() -> datetime: + return datetime.now(tz=timezone.utc) + + +def new_preimage_bytes() -> tuple[bytes, bytes]: + preimage = os.urandom(32) + return preimage, sha256(preimage).digest() + + +def new_preimage() -> tuple[str, str]: + preimage = os.urandom(32) + return preimage.hex(), sha256(preimage).hexdigest() + + +def lightning(*args: str, node: int = 2) -> dict[str, Any]: return json.load( os.popen( f"docker exec boltz-cln-{node} lightning-cli --regtest {' '.join(args)}", @@ -25,11 +40,6 @@ def lnd_raw(*args: str, node: int = 1) -> str: ).read() -def new_preimage() -> tuple[str, str]: - preimage = os.urandom(32) - return preimage.hex(), sha256(preimage).hexdigest() - - class LndPay(Thread): res: dict[str, Any] = None diff --git a/tests/poetry.lock b/tests/poetry.lock index 85049b9..5f2e11b 100644 --- a/tests/poetry.lock +++ b/tests/poetry.lock @@ -25,6 +25,124 @@ files = [ [package.extras] test = ["pytest (>=6)"] +[[package]] +name = "grpcio" +version = "1.65.5" +description = "HTTP/2-based RPC framework" +optional = false +python-versions = ">=3.8" +files = [ + {file = "grpcio-1.65.5-cp310-cp310-linux_armv7l.whl", hash = "sha256:b67d450f1e008fedcd81e097a3a400a711d8be1a8b20f852a7b8a73fead50fe3"}, + {file = "grpcio-1.65.5-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:a70a20eed87bba647a38bedd93b3ce7db64b3f0e8e0952315237f7f5ca97b02d"}, + {file = "grpcio-1.65.5-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:f79c87c114bf37adf408026b9e2e333fe9ff31dfc9648f6f80776c513145c813"}, + {file = "grpcio-1.65.5-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f17f9fa2d947dbfaca01b3ab2c62eefa8240131fdc67b924eb42ce6032e3e5c1"}, + {file = "grpcio-1.65.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:32d60e18ff7c34fe3f6db3d35ad5c6dc99f5b43ff3982cb26fad4174462d10b1"}, + {file = "grpcio-1.65.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:fe6505376f5b00bb008e4e1418152e3ad3d954b629da286c7913ff3cfc0ff740"}, + {file = "grpcio-1.65.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:33158e56c6378063923c417e9fbdb28660b6e0e2835af42e67f5a7793f587af7"}, + {file = "grpcio-1.65.5-cp310-cp310-win32.whl", hash = "sha256:1cbc208edb9acf1cc339396a1a36b83796939be52f34e591c90292045b579fbf"}, + {file = "grpcio-1.65.5-cp310-cp310-win_amd64.whl", hash = "sha256:bc74f3f745c37e2c5685c9d2a2d5a94de00f286963f5213f763ae137bf4f2358"}, + {file = "grpcio-1.65.5-cp311-cp311-linux_armv7l.whl", hash = "sha256:3207ae60d07e5282c134b6e02f9271a2cb523c6d7a346c6315211fe2bf8d61ed"}, + {file = "grpcio-1.65.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a2f80510f99f82d4eb825849c486df703f50652cea21c189eacc2b84f2bde764"}, + {file = "grpcio-1.65.5-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:a80e9a5e3f93c54f5eb82a3825ea1fc4965b2fa0026db2abfecb139a5c4ecdf1"}, + {file = "grpcio-1.65.5-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0b2944390a496567de9e70418f3742b477d85d8ca065afa90432edc91b4bb8ad"}, + {file = "grpcio-1.65.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c3655139d7be213c32c79ef6fb2367cae28e56ef68e39b1961c43214b457f257"}, + {file = "grpcio-1.65.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:05f02d68fc720e085f061b704ee653b181e6d5abfe315daef085719728d3d1fd"}, + {file = "grpcio-1.65.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1c4caafe71aef4dabf53274bbf4affd6df651e9f80beedd6b8e08ff438ed3260"}, + {file = "grpcio-1.65.5-cp311-cp311-win32.whl", hash = "sha256:84c901cdec16a092099f251ef3360d15e29ef59772150fa261d94573612539b5"}, + {file = "grpcio-1.65.5-cp311-cp311-win_amd64.whl", hash = "sha256:11f8b16121768c1cb99d7dcb84e01510e60e6a206bf9123e134118802486f035"}, + {file = "grpcio-1.65.5-cp312-cp312-linux_armv7l.whl", hash = "sha256:ee6ed64a27588a2c94e8fa84fe8f3b5c89427d4d69c37690903d428ec61ca7e4"}, + {file = "grpcio-1.65.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:76991b7a6fb98630a3328839755181ce7c1aa2b1842aa085fd4198f0e5198960"}, + {file = "grpcio-1.65.5-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:89c00a18801b1ed9cc441e29b521c354725d4af38c127981f2c950c796a09b6e"}, + {file = "grpcio-1.65.5-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:078038e150a897e5e402ed3d57f1d31ebf604cbed80f595bd281b5da40762a92"}, + {file = "grpcio-1.65.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c97962720489ef31b5ad8a916e22bc31bba3664e063fb9f6702dce056d4aa61b"}, + {file = "grpcio-1.65.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:b8270b15b99781461b244f5c81d5c2bc9696ab9189fb5ff86c841417fb3b39fe"}, + {file = "grpcio-1.65.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8e5c4c15ac3fe1eb68e46bc51e66ad29be887479f231f8237cf8416058bf0cc1"}, + {file = "grpcio-1.65.5-cp312-cp312-win32.whl", hash = "sha256:f5b5970341359341d0e4c789da7568264b2a89cd976c05ea476036852b5950cd"}, + {file = "grpcio-1.65.5-cp312-cp312-win_amd64.whl", hash = "sha256:238a625f391a1b9f5f069bdc5930f4fd71b74426bea52196fc7b83f51fa97d34"}, + {file = "grpcio-1.65.5-cp38-cp38-linux_armv7l.whl", hash = "sha256:6c4e62bcf297a1568f627f39576dbfc27f1e5338a691c6dd5dd6b3979da51d1c"}, + {file = "grpcio-1.65.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:d7df567b67d16d4177835a68d3f767bbcbad04da9dfb52cbd19171f430c898bd"}, + {file = "grpcio-1.65.5-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:b7ca419f1462390851eec395b2089aad1e49546b52d4e2c972ceb76da69b10f8"}, + {file = "grpcio-1.65.5-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fa36dd8496d3af0d40165252a669fa4f6fd2db4b4026b9a9411cbf060b9d6a15"}, + {file = "grpcio-1.65.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a101696f9ece90a0829988ff72f1b1ea2358f3df035bdf6d675dd8b60c2c0894"}, + {file = "grpcio-1.65.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:2a6d8169812932feac514b420daffae8ab8e36f90f3122b94ae767e633296b17"}, + {file = "grpcio-1.65.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:47d0aaaab82823f0aa6adea5184350b46e2252e13a42a942db84da5b733f2e05"}, + {file = "grpcio-1.65.5-cp38-cp38-win32.whl", hash = "sha256:85ae8f8517d5bcc21fb07dbf791e94ed84cc28f84c903cdc2bd7eaeb437c8f45"}, + {file = "grpcio-1.65.5-cp38-cp38-win_amd64.whl", hash = "sha256:770bd4bd721961f6dd8049bc27338564ba8739913f77c0f381a9815e465ff965"}, + {file = "grpcio-1.65.5-cp39-cp39-linux_armv7l.whl", hash = "sha256:ab5ec837d8cee8dbce9ef6386125f119b231e4333cc6b6d57b6c5c7c82a72331"}, + {file = "grpcio-1.65.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:cabd706183ee08d8026a015af5819a0b3a8959bdc9d1f6fdacd1810f09200f2a"}, + {file = "grpcio-1.65.5-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:ec71fc5b39821ad7d80db7473c8f8c2910f3382f0ddadfbcfc2c6c437107eb67"}, + {file = "grpcio-1.65.5-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d3a9e35bcb045e39d7cac30464c285389b9a816ac2067e4884ad2c02e709ef8e"}, + {file = "grpcio-1.65.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d750e9330eb14236ca11b78d0c494eed13d6a95eb55472298f0e547c165ee324"}, + {file = "grpcio-1.65.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:2b91ce647b6307f25650872454a4d02a2801f26a475f90d0b91ed8110baae589"}, + {file = "grpcio-1.65.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8da58ff80bc4556cf29bc03f5fff1f03b8387d6aaa7b852af9eb65b2cf833be4"}, + {file = "grpcio-1.65.5-cp39-cp39-win32.whl", hash = "sha256:7a412959aa5f08c5ac04aa7b7c3c041f5e4298cadd4fcc2acff195b56d185ebc"}, + {file = "grpcio-1.65.5-cp39-cp39-win_amd64.whl", hash = "sha256:55714ea852396ec9568f45f487639945ab674de83c12bea19d5ddbc3ae41ada3"}, + {file = "grpcio-1.65.5.tar.gz", hash = "sha256:ec6f219fb5d677a522b0deaf43cea6697b16f338cb68d009e30930c4aa0d2209"}, +] + +[package.extras] +protobuf = ["grpcio-tools (>=1.65.5)"] + +[[package]] +name = "grpcio-tools" +version = "1.65.5" +description = "Protobuf code generator for gRPC" +optional = false +python-versions = ">=3.8" +files = [ + {file = "grpcio_tools-1.65.5-cp310-cp310-linux_armv7l.whl", hash = "sha256:f141f247a93e4c7faf33ac683a9cab93bb6570946a219260d33e2e62079db6e8"}, + {file = "grpcio_tools-1.65.5-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:a6d05950c62024ac54dfb7b7987fd45e22e832143aa88768439aa12073e9d035"}, + {file = "grpcio_tools-1.65.5-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:675df59961e2ab7808a3c0222ad995d8886bbbb7e77000fba1059214c9ce3e09"}, + {file = "grpcio_tools-1.65.5-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fe5a21e4970cc2555066ba37c7c743749ccd0bd056d4262e97678927c586def8"}, + {file = "grpcio_tools-1.65.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d0d7d34b4b3fba78075a923de2f962b33bcc04926569966c00219d5f41f2589"}, + {file = "grpcio_tools-1.65.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:474d5905ee0700662b42f71ce2fc5901786c88d5a54c08749fa5bccae1db27af"}, + {file = "grpcio_tools-1.65.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0f698f34be22a89426f986310ee866b8faa812355aab5d241fdaf742b546c36c"}, + {file = "grpcio_tools-1.65.5-cp310-cp310-win32.whl", hash = "sha256:3d8cee4c1f0bca80115cfa99f25ab6e6c6797b4443b1f0d5fa949bf2e9ac5af9"}, + {file = "grpcio_tools-1.65.5-cp310-cp310-win_amd64.whl", hash = "sha256:ac013d5d118dfafc887c3da1649dbd5087a7161d969dab236050e54c55fa0725"}, + {file = "grpcio_tools-1.65.5-cp311-cp311-linux_armv7l.whl", hash = "sha256:553b3f406a681719f6c11e70c993fe77383ab6adead9173ad1c6a611e5aaaf48"}, + {file = "grpcio_tools-1.65.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2a520fbb9be5a05b5a0cdb5c5d481f63fea5db2f048f47f19b613685009890f2"}, + {file = "grpcio_tools-1.65.5-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:eca7be231ba6de3ac38556dcba1f94c05422e7cc62341bc2787ac9881aed3026"}, + {file = "grpcio_tools-1.65.5-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cd1e9134e266fefdd49e1c9989d1bdf74578a9f237d7d9df01d871d898deda9b"}, + {file = "grpcio_tools-1.65.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:777243e4f7152da9d226d9cc1e6d7c2b94335e267c618260e6255a063bb7dfcb"}, + {file = "grpcio_tools-1.65.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:a2e63bf9b6444f28ec684faf3c5fc8394b035fe221842186c3b9ff0121c20534"}, + {file = "grpcio_tools-1.65.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:969c0b5079beb08ae0a22237652289bfc0e34602403e040bab419f46cb775e50"}, + {file = "grpcio_tools-1.65.5-cp311-cp311-win32.whl", hash = "sha256:b9aefd9dc742c20bc5fb16f497f6d04b4f4f5c7d44cc86654a334ce7ea9c8021"}, + {file = "grpcio_tools-1.65.5-cp311-cp311-win_amd64.whl", hash = "sha256:ba27d67421dad33cbb42cdcd144dabed0516f0a5ee48d37250dd1b37c97cca72"}, + {file = "grpcio_tools-1.65.5-cp312-cp312-linux_armv7l.whl", hash = "sha256:b48943492a7c00a3ce6d7159c37761d006085f7dcd4a13931dcc74ecb8a24b56"}, + {file = "grpcio_tools-1.65.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:ef44822eee4834158eb03cd432e4cf7e716d7d03051cc8314be4956ee9e9da3f"}, + {file = "grpcio_tools-1.65.5-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:6077a87bb3028797175dd437e08ff42b559045f9588a14eb9c943dd8bde32dcc"}, + {file = "grpcio_tools-1.65.5-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8ee220c430f87378c598b7217c8c32ce7aeab3d8a93bc92cee92ce6940d870dd"}, + {file = "grpcio_tools-1.65.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c86a003bfcbf98b6261a89c2aad97197672c99d057fe441440210f052c9b54f1"}, + {file = "grpcio_tools-1.65.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:475ef5e8d91cbcf9bd9edbf51ac135931853d1c2fe6f8ae0c496b9ef422b41e4"}, + {file = "grpcio_tools-1.65.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e680b32e90c42d08363a02e9971e690bcf2509cb7bf647e232113b3e777eac9a"}, + {file = "grpcio_tools-1.65.5-cp312-cp312-win32.whl", hash = "sha256:cc6b010bc26566ca35e858a94daa18992a02e7b70f688a78f3308dada54fc063"}, + {file = "grpcio_tools-1.65.5-cp312-cp312-win_amd64.whl", hash = "sha256:3ddce72654ce415cbe36561b5e124fc0fcb461582e829016b7aa726824bcadc9"}, + {file = "grpcio_tools-1.65.5-cp38-cp38-linux_armv7l.whl", hash = "sha256:e5ae4a000c3344c32c1fa63e137ef42e65eae9adb5576dab636e3bc092653ae6"}, + {file = "grpcio_tools-1.65.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:23bce4fcee7cad2e085923fdfd65ed2bd2173bfc298c8c8964d3dddaef1f49ae"}, + {file = "grpcio_tools-1.65.5-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:56617905a4e478132b3732fd9dda71e35f1e7adedd34c92248c9a04a3892cb01"}, + {file = "grpcio_tools-1.65.5-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5c38a8dc81900b7211fc5b1a14ace7f4ffd8cfbfd17e504f40044f0918b99825"}, + {file = "grpcio_tools-1.65.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13b4f00f66a3f024e9bfaf535e2be8a373ada199eb928507945685208bf29536"}, + {file = "grpcio_tools-1.65.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:b2072ad56bec624d0190e605c6b56205a6336f31a35617b90d927791c14aa4ad"}, + {file = "grpcio_tools-1.65.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:c8f8241b859413b8f0c5c8cfd4d9021862d29cf090e60fb8b30968737b575b52"}, + {file = "grpcio_tools-1.65.5-cp38-cp38-win32.whl", hash = "sha256:e099bff2328931064aef565e811a7ce6ecbe7359c4d377534eee12dc6c35deb8"}, + {file = "grpcio_tools-1.65.5-cp38-cp38-win_amd64.whl", hash = "sha256:bf78ed1cfc9304dca4d1a5ec578a91b65a5946bf4ee923358a721fb47e35ffdf"}, + {file = "grpcio_tools-1.65.5-cp39-cp39-linux_armv7l.whl", hash = "sha256:02ed771ce6aea1a5620d818ae41380a7fcf65c6d499c53d1ddaf6ded882640a9"}, + {file = "grpcio_tools-1.65.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5b6a50253f950fd02caff90a021d6564731a86ffad38b7c0a76423f6ed58e779"}, + {file = "grpcio_tools-1.65.5-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:8848d509b88631be77b4c40119c02a37d0e884d10b10f0ddb1e3e551d7023b0d"}, + {file = "grpcio_tools-1.65.5-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:853ebfa33ed5336b51d0fa5d068bd5b42cb84d09077670ffa6b2dc7980f000cd"}, + {file = "grpcio_tools-1.65.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:221fd8f4c3f54ced15d9dac2b8800fd1b254bf9cd29414d500ce6f7ddb59be25"}, + {file = "grpcio_tools-1.65.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:b6b33e23bfc6919c71329dabec632e7693de62efbed24b3e34616c09827909d8"}, + {file = "grpcio_tools-1.65.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:21122fa43c48e15ff0d656258f942fdf7c3ed2b7ab1530c7d37d3027b71a5872"}, + {file = "grpcio_tools-1.65.5-cp39-cp39-win32.whl", hash = "sha256:0e092c51089251f41e6e2c03519311509162be3aba2c71a91983d7d86ed300f3"}, + {file = "grpcio_tools-1.65.5-cp39-cp39-win_amd64.whl", hash = "sha256:2819a3a50c61306074cc95938db97e365acfca873b2cce986ad2d1f519d51f2f"}, + {file = "grpcio_tools-1.65.5.tar.gz", hash = "sha256:7c3a47ad0070bc907c7818caf55aa1948e9282d24e27afd21015872a25594bc7"}, +] + +[package.dependencies] +grpcio = ">=1.65.5" +protobuf = ">=5.26.1,<6.0dev" +setuptools = "*" + [[package]] name = "iniconfig" version = "2.0.0" @@ -62,6 +180,26 @@ files = [ dev = ["pre-commit", "tox"] testing = ["pytest", "pytest-benchmark"] +[[package]] +name = "protobuf" +version = "5.27.3" +description = "" +optional = false +python-versions = ">=3.8" +files = [ + {file = "protobuf-5.27.3-cp310-abi3-win32.whl", hash = "sha256:dcb307cd4ef8fec0cf52cb9105a03d06fbb5275ce6d84a6ae33bc6cf84e0a07b"}, + {file = "protobuf-5.27.3-cp310-abi3-win_amd64.whl", hash = "sha256:16ddf3f8c6c41e1e803da7abea17b1793a97ef079a912e42351eabb19b2cffe7"}, + {file = "protobuf-5.27.3-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:68248c60d53f6168f565a8c76dc58ba4fa2ade31c2d1ebdae6d80f969cdc2d4f"}, + {file = "protobuf-5.27.3-cp38-abi3-manylinux2014_aarch64.whl", hash = "sha256:b8a994fb3d1c11156e7d1e427186662b64694a62b55936b2b9348f0a7c6625ce"}, + {file = "protobuf-5.27.3-cp38-abi3-manylinux2014_x86_64.whl", hash = "sha256:a55c48f2a2092d8e213bd143474df33a6ae751b781dd1d1f4d953c128a415b25"}, + {file = "protobuf-5.27.3-cp38-cp38-win32.whl", hash = "sha256:043853dcb55cc262bf2e116215ad43fa0859caab79bb0b2d31b708f128ece035"}, + {file = "protobuf-5.27.3-cp38-cp38-win_amd64.whl", hash = "sha256:c2a105c24f08b1e53d6c7ffe69cb09d0031512f0b72f812dd4005b8112dbe91e"}, + {file = "protobuf-5.27.3-cp39-cp39-win32.whl", hash = "sha256:c84eee2c71ed83704f1afbf1a85c3171eab0fd1ade3b399b3fad0884cbcca8bf"}, + {file = "protobuf-5.27.3-cp39-cp39-win_amd64.whl", hash = "sha256:af7c0b7cfbbb649ad26132e53faa348580f844d9ca46fd3ec7ca48a1ea5db8a1"}, + {file = "protobuf-5.27.3-py3-none-any.whl", hash = "sha256:8572c6533e544ebf6899c360e91d6bcbbee2549251643d32c52cf8a5de295ba5"}, + {file = "protobuf-5.27.3.tar.gz", hash = "sha256:82460903e640f2b7e34ee81a947fdaad89de796d324bcbc38ff5430bcdead82c"}, +] + [[package]] name = "pytest" version = "8.3.2" @@ -111,6 +249,22 @@ files = [ {file = "ruff-0.6.1.tar.gz", hash = "sha256:af3ffd8c6563acb8848d33cd19a69b9bfe943667f0419ca083f8ebe4224a3436"}, ] +[[package]] +name = "setuptools" +version = "73.0.1" +description = "Easily download, build, install, upgrade, and uninstall Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "setuptools-73.0.1-py3-none-any.whl", hash = "sha256:b208925fcb9f7af924ed2dc04708ea89791e24bde0d3020b27df0e116088b34e"}, + {file = "setuptools-73.0.1.tar.gz", hash = "sha256:d59a3e788ab7e012ab2c4baed1b376da6366883ee20d7a5fc426816e3d7b1193"}, +] + +[package.extras] +core = ["importlib-metadata (>=6)", "importlib-resources (>=5.10.2)", "jaraco.text (>=3.7)", "more-itertools (>=8.8)", "packaging (>=24)", "platformdirs (>=2.6.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"] +doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier", "towncrier (<24.7)"] +test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test", "mypy (==1.11.*)", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy", "pytest-perf", "pytest-ruff (<0.4)", "pytest-ruff (>=0.2.1)", "pytest-ruff (>=0.3.2)", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] + [[package]] name = "tomli" version = "2.0.1" @@ -125,4 +279,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = "^3.10" -content-hash = "1d452508104c22c9af0db099221f49dd2ca3cea667098d160502c4bd53846cdb" +content-hash = "af0e063a00ac6f3479fccf071d82a107f21eb9cae18e87188565a90d353cbc2c" diff --git a/tests/pyproject.toml b/tests/pyproject.toml index 3735120..6f979a8 100644 --- a/tests/pyproject.toml +++ b/tests/pyproject.toml @@ -1,20 +1,27 @@ [tool.poetry] -name = "tests" +name = "hold" authors = ["Boltz"] description = "Test for CLN hold invoice plugin" version = "0.1.0" license = "MIT" -package-mode = false [tool.poetry.dependencies] python = "^3.10" pytest = "^8.3.2" ruff = "^0.6.1" +grpcio = "^1.65.5" +grpcio-tools = "^1.65.5" [build-system] requires = ["poetry-core"] build-backend = "poetry.core.masonry.api" +[tool.ruff] +exclude = ["hold/protos"] + [tool.ruff.lint] select = ["ALL"] -ignore = ["D100", "D101", "D102", "D103", "D107", "D211", "D212", "S605", "D203", "ISC001", "COM812", "S101"] +ignore = [ + "D100", "D101", "D102", "D103", "D104", "D107", "D211", "D212", "S605", "D203", "ISC001", "COM812", "S101", + "PLR2004" +]