From 88393fa4c4e667116e7c5a0e63784536f8a62040 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?dni=20=E2=9A=A1?= Date: Thu, 24 Aug 2023 09:47:47 +0200 Subject: [PATCH] [DEV] add ruff and remove isort and flake (#300) * [DEV] add ruff and remove isort and flake - precommit - workflow - Makefile updated black * configure black to use default line-length * reformat to 88 chars line-length * fix ugly comments --- .flake8 | 8 -- .github/workflows/checks.yml | 11 +-- .pre-commit-config.yaml | 16 ++-- Makefile | 15 ++-- cashu/core/base.py | 36 ++++----- cashu/core/bolt11.py | 1 - cashu/core/db.py | 6 +- cashu/core/migrations.py | 6 +- cashu/core/script.py | 6 +- cashu/mint/app.py | 11 ++- cashu/mint/crud.py | 12 +-- cashu/mint/ledger.py | 58 ++++++++------ cashu/mint/migrations.py | 60 +++++--------- cashu/mint/router.py | 38 ++++++--- cashu/mint/startup.py | 3 +- cashu/wallet/api/router.py | 5 +- cashu/wallet/cli/cli.py | 55 ++++++++----- cashu/wallet/cli/cli_helpers.py | 3 +- cashu/wallet/crud.py | 12 +-- cashu/wallet/helpers.py | 3 +- cashu/wallet/migrations.py | 60 +++++--------- cashu/wallet/nostr.py | 5 +- cashu/wallet/wallet.py | 9 ++- poetry.lock | 135 +++++++++++++------------------- pyproject.toml | 64 ++++++++++++++- tests/test_wallet.py | 52 +++++------- 26 files changed, 357 insertions(+), 333 deletions(-) delete mode 100644 .flake8 diff --git a/.flake8 b/.flake8 deleted file mode 100644 index c64e6e9..0000000 --- a/.flake8 +++ /dev/null @@ -1,8 +0,0 @@ -[flake8] -max-line-length = 150 -exclude = cashu/nostr, cashu/core/bolt11.py -ignore = - # E203 whitespace before ':' black does not like it - E203, - # W503: line break before binary operator - W503, diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 8ba2d5c..e001f35 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -24,9 +24,7 @@ jobs: run: poetry install - name: Check black run: make black-check - - name: Check isort - run: make isort-check - linting: + mypy: runs-on: ubuntu-latest strategy: matrix: @@ -49,5 +47,8 @@ jobs: run: yes | poetry run mypy cashu --install-types || true - name: Run mypy run: poetry run mypy cashu --ignore-missing - - name: Run flake8 - run: poetry run flake8 + ruff: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: chartboost/ruff-action@v1 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 8bba7a2..22f3090 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,5 +1,4 @@ exclude: '^cashu/nostr/.*' - repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.3.0 @@ -14,16 +13,11 @@ repos: - id: mixed-line-ending - id: check-case-conflict - repo: https://github.com/psf/black - rev: 22.6.0 + rev: 23.7.0 hooks: - id: black - - repo: https://github.com/pycqa/isort - rev: 5.12.0 + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.0.283 hooks: - - id: isort - args: ['--profile', 'black'] - - repo: https://github.com/pycqa/flake8 - rev: 6.0.0 - hooks: - - id: flake8 - entry: poetry run flake8 + - id: ruff + args: [ --fix, --exit-non-zero-on-fix ] diff --git a/Makefile b/Makefile index 3e17cb2..fb3cbfa 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ -isort: - poetry run isort --profile black . --skip cashu/nostr +ruff: + poetry run ruff check . --fix -isort-check: - poetry run isort --profile black --check-only . --skip cashu/nostr +ruff-check: + poetry run ruff check . black: poetry run black . --exclude cashu/nostr @@ -13,12 +13,9 @@ black-check: mypy: poetry run mypy cashu --ignore-missing -flake8: - poetry run flake8 cashu +format: black ruff -format: isort black - -check: isort-check black-check flake8 mypy +check: black-check ruff-check mypy clean: rm -r cashu.egg-info/ || true diff --git a/cashu/core/base.py b/cashu/core/base.py index 3860e62..525b4b6 100644 --- a/cashu/core/base.py +++ b/cashu/core/base.py @@ -22,8 +22,8 @@ class SecretKind: class SigFlags: - SIG_INPUTS = ( - "SIG_INPUTS" # require signatures only on the inputs (default signature flag) + SIG_INPUTS = ( # require signatures only on the inputs (default signature flag) + "SIG_INPUTS" ) SIG_ALL = "SIG_ALL" # require signatures on inputs and outputs @@ -159,20 +159,17 @@ class Proof(BaseModel): Value token """ - id: Union[ - None, str - ] = "" # NOTE: None for backwards compatibility for old clients that do not include the keyset id < 0.3 + # NOTE: None for backwards compatibility for old clients that do not include the keyset id < 0.3 + id: Union[None, str] = "" amount: int = 0 secret: str = "" # secret or message to be blinded and signed C: str = "" # signature on secret, unblinded by wallet p2pksigs: Union[List[str], None] = [] # P2PK signature p2shscript: Union[P2SHScript, None] = None # P2SH spending condition - reserved: Union[ - None, bool - ] = False # whether this proof is reserved for sending, used for coin management in the wallet - send_id: Union[ - None, str - ] = "" # unique ID of send attempt, used for grouping pending tokens in the wallet + # whether this proof is reserved for sending, used for coin management in the wallet + reserved: Union[None, bool] = False + # unique ID of send attempt, used for grouping pending tokens in the wallet + send_id: Union[None, str] = "" time_created: Union[None, str] = "" time_reserved: Union[None, str] = "" derivation_path: Union[None, str] = "" # derivation path of the proof @@ -338,9 +335,9 @@ class CheckSpendableRequest(BaseModel): class CheckSpendableResponse(BaseModel): spendable: List[bool] - pending: Optional[ - List[bool] - ] = None # TODO: Uncomment when all mints are updated to 0.12.3 and support /check + pending: Optional[List[bool]] = ( + None # TODO: Uncomment when all mints are updated to 0.12.3 and support /check + ) # with pending tokens (kept for backwards compatibility of new wallets with old mints) @@ -421,9 +418,11 @@ class WalletKeyset: return cls( id=row["id"], - public_keys=deserialize(str(row["public_keys"])) - if dict(row).get("public_keys") - else {}, + public_keys=( + deserialize(str(row["public_keys"])) + if dict(row).get("public_keys") + else {} + ), mint_url=row["mint_url"], valid_from=row["valid_from"], valid_to=row["valid_to"], @@ -489,7 +488,8 @@ class MintKeyset: self.id = derive_keyset_id(self.public_keys) # type: ignore if backwards_compatibility_pre_0_12: logger.warning( - f"WARNING: Using weak key derivation for keyset {self.id} (backwards compatibility < 0.12)" + f"WARNING: Using weak key derivation for keyset {self.id} (backwards" + " compatibility < 0.12)" ) diff --git a/cashu/core/bolt11.py b/cashu/core/bolt11.py index 962581d..3c59fbb 100644 --- a/cashu/core/bolt11.py +++ b/cashu/core/bolt11.py @@ -184,7 +184,6 @@ def lnencode(addr, privkey): tags_set = set() for k, v in addr.tags: - # BOLT #11: # # A writer MUST NOT include more than one `d`, `h`, `n` or `x` fields, diff --git a/cashu/core/db.py b/cashu/core/db.py index 0af326a..6087386 100644 --- a/cashu/core/db.py +++ b/cashu/core/db.py @@ -117,9 +117,9 @@ class Database(Compat): psycopg2.extensions.new_type( # type: ignore (1082, 1083, 1266), "DATE2INT", - lambda value, curs: time.mktime(value.timetuple()) - if value is not None - else None, + lambda value, curs: ( + time.mktime(value.timetuple()) if value is not None else None + ), ) ) diff --git a/cashu/core/migrations.py b/cashu/core/migrations.py index 37a697c..ce3e2bf 100644 --- a/cashu/core/migrations.py +++ b/cashu/core/migrations.py @@ -37,11 +37,13 @@ async def migrate_databases(db: Database, migrations_module): exists = None if conn.type == SQLITE: exists = await conn.fetchone( - f"SELECT * FROM sqlite_master WHERE type='table' AND name='{table_with_schema(db, 'dbversions')}'" + "SELECT * FROM sqlite_master WHERE type='table' AND" + f" name='{table_with_schema(db, 'dbversions')}'" ) elif conn.type in {POSTGRES, COCKROACH}: exists = await conn.fetchone( - f"SELECT * FROM information_schema.tables WHERE table_name = '{table_with_schema(db, 'dbversions')}'" + "SELECT * FROM information_schema.tables WHERE table_name =" + f" '{table_with_schema(db, 'dbversions')}'" ) if not exists: diff --git a/cashu/core/script.py b/cashu/core/script.py index ff471d1..0fc2a8e 100644 --- a/cashu/core/script.py +++ b/cashu/core/script.py @@ -134,7 +134,8 @@ if __name__ == "__main__": txin_redeemScript_b64 = base64.urlsafe_b64encode(txin_redeemScript).decode() txin_signature_b64 = base64.urlsafe_b64encode(txin_signature).decode() print( - f"Carol to Bob:\nscript: {txin_redeemScript.__repr__()}\nscript: {txin_redeemScript_b64}\nsignature: {txin_signature_b64}\n" + f"Carol to Bob:\nscript: {txin_redeemScript.__repr__()}\nscript:" + f" {txin_redeemScript_b64}\nsignature: {txin_signature_b64}\n" ) print("") # --------- @@ -155,7 +156,8 @@ if __name__ == "__main__": tx, _ = step1_bob_carol_create_tx(txin_p2sh_address) print( - f"Bob verifies:\nscript: {txin_redeemScript_b64}\nsignature: {txin_signature_b64}\n" + f"Bob verifies:\nscript: {txin_redeemScript_b64}\nsignature:" + f" {txin_signature_b64}\n" ) script_valid = step3_bob_verify_script(txin_signature, txin_redeemScript, tx) # MINT redeems tokens and stores P2SH:txin_p2sh_address diff --git a/cashu/mint/app.py b/cashu/mint/app.py index 3b4ef32..412cd90 100644 --- a/cashu/mint/app.py +++ b/cashu/mint/app.py @@ -36,11 +36,16 @@ def create_app(config_object="core.settings") -> FastAPI: class Formatter: def __init__(self): self.padding = 0 - self.minimal_fmt: str = "{time:YYYY-MM-DD HH:mm:ss.SS} | {level} | {message}\n" + self.minimal_fmt: str = ( + "{time:YYYY-MM-DD HH:mm:ss.SS} |" + " {level} | {message}\n" + ) if settings.debug: self.fmt: str = ( - "{time:YYYY-MM-DD HH:mm:ss.SS} | {level: <4} | {name}:" - "{function}:{line} | {message}\n" + "{time:YYYY-MM-DD HH:mm:ss.SS} | {level:" + " <4} |" + " {name}:{function}:{line}" + " | {message}\n" ) else: self.fmt: str = self.minimal_fmt diff --git a/cashu/mint/crud.py b/cashu/mint/crud.py index c7eaffc..d15ab22 100644 --- a/cashu/mint/crud.py +++ b/cashu/mint/crud.py @@ -90,11 +90,9 @@ async def get_proofs_used( db: Database, conn: Optional[Connection] = None, ): - rows = await (conn or db).fetchall( - f""" + rows = await (conn or db).fetchall(f""" SELECT secret from {table_with_schema(db, 'proofs_used')} - """ - ) + """) return [row[0] for row in rows] @@ -123,11 +121,9 @@ async def get_proofs_pending( db: Database, conn: Optional[Connection] = None, ): - rows = await (conn or db).fetchall( - f""" + rows = await (conn or db).fetchall(f""" SELECT * from {table_with_schema(db, 'proofs_pending')} - """ - ) + """) return [Proof(**r) for r in rows] diff --git a/cashu/mint/ledger.py b/cashu/mint/ledger.py index 1544c11..8f972d5 100644 --- a/cashu/mint/ledger.py +++ b/cashu/mint/ledger.py @@ -276,9 +276,10 @@ class Ledger: if not valid: raise TransactionError("script invalid.") # check if secret commits to script address - assert secret.data == str( - txin_p2sh_address - ), f"secret does not contain correct P2SH address: {secret.data} is not {txin_p2sh_address}." + assert secret.data == str(txin_p2sh_address), ( + f"secret does not contain correct P2SH address: {secret.data} is not" + f" {txin_p2sh_address}." + ) return True # P2PK @@ -310,9 +311,10 @@ class Ledger: assert n_sigs_required > 0, "n_sigs must be positive." # check if enough signatures are present - assert ( - len(proof.p2pksigs) >= n_sigs_required - ), f"not enough signatures provided: {len(proof.p2pksigs)} < {n_sigs_required}." + assert len(proof.p2pksigs) >= n_sigs_required, ( + f"not enough signatures provided: {len(proof.p2pksigs)} <" + f" {n_sigs_required}." + ) n_valid_sigs_per_output = 0 # loop over all signatures in output @@ -327,20 +329,24 @@ class Ledger: ): n_valid_sigs_per_output += 1 logger.trace( - f"p2pk signature on input is valid: {input_sig} on {pubkey}." + f"p2pk signature on input is valid: {input_sig} on" + f" {pubkey}." ) continue else: logger.trace( - f"p2pk signature on input is invalid: {input_sig} on {pubkey}." + f"p2pk signature on input is invalid: {input_sig} on" + f" {pubkey}." ) # check if we have enough valid signatures assert n_valid_sigs_per_output, "no valid signature provided for input." - assert ( - n_valid_sigs_per_output >= n_sigs_required - ), f"signature threshold not met. {n_valid_sigs_per_output} < {n_sigs_required}." + assert n_valid_sigs_per_output >= n_sigs_required, ( + f"signature threshold not met. {n_valid_sigs_per_output} <" + f" {n_sigs_required}." + ) logger.trace( - f"{n_valid_sigs_per_output} of {n_sigs_required} valid signatures found." + f"{n_valid_sigs_per_output} of {n_sigs_required} valid signatures" + " found." ) logger.trace(proof.p2pksigs) @@ -424,11 +430,13 @@ class Ledger: ): n_valid_sigs_per_output += 1 assert n_valid_sigs_per_output, "no valid signature provided for output." - assert ( - n_valid_sigs_per_output >= n_sigs_required - ), f"signature threshold not met. {n_valid_sigs_per_output} < {n_sigs_required}." + assert n_valid_sigs_per_output >= n_sigs_required, ( + f"signature threshold not met. {n_valid_sigs_per_output} <" + f" {n_sigs_required}." + ) logger.trace( - f"{n_valid_sigs_per_output} of {n_sigs_required} valid signatures found." + f"{n_valid_sigs_per_output} of {n_sigs_required} valid signatures" + " found." ) logger.trace(output.p2pksigs) logger.trace("p2pk signatures on output is valid.") @@ -492,7 +500,8 @@ class Ledger: Tuple[str, str]: Bolt11 invoice and payment hash (for lookup) """ logger.trace( - f"_request_lightning_invoice: Requesting Lightning invoice for {amount} satoshis." + "_request_lightning_invoice: Requesting Lightning invoice for" + f" {amount} satoshis." ) error, balance = await self.lightning.status() logger.trace(f"_request_lightning_invoice: Lightning wallet balance: {balance}") @@ -549,14 +558,16 @@ class Ledger: try: if amount > invoice.amount: raise LightningError( - f"requested amount too high: {amount}. Invoice amount: {invoice.amount}" + f"requested amount too high: {amount}. Invoice amount:" + f" {invoice.amount}" ) logger.trace( f"_check_lightning_invoice: checking invoice {invoice.payment_hash}" ) status = await self.lightning.get_invoice_status(invoice.payment_hash) logger.trace( - f"_check_lightning_invoice: invoice {invoice.payment_hash} status: {status}" + f"_check_lightning_invoice: invoice {invoice.payment_hash} status:" + f" {status}" ) if status.paid: return status.paid @@ -658,7 +669,8 @@ class Ledger: try: for p in proofs: logger.trace( - f"crud: _unset_proofs_pending unsetting proof {p.secret} as pending" + f"crud: _unset_proofs_pending unsetting proof {p.secret} as" + " pending" ) await self.crud.unset_proof_pending(proof=p, db=self.db, conn=conn) logger.trace( @@ -1005,7 +1017,8 @@ class Ledger: decoded_invoice = bolt11.decode(pr) amount = math.ceil(decoded_invoice.amount_msat / 1000) logger.trace( - f"check_fees: checking lightning invoice: {decoded_invoice.payment_hash}" + "check_fees: checking lightning invoice:" + f" {decoded_invoice.payment_hash}" ) paid = await self.lightning.get_invoice_status(decoded_invoice.payment_hash) logger.trace(f"check_fees: paid: {paid}") @@ -1071,7 +1084,8 @@ class Ledger: # BEGIN backwards compatibility < 0.13.0 if amount is not None: logger.debug( - "Split: Client provided `amount` - backwards compatibility response pre 0.13.0" + "Split: Client provided `amount` - backwards compatibility response pre" + " 0.13.0" ) # split outputs according to amount total = sum_proofs(proofs) diff --git a/cashu/mint/migrations.py b/cashu/mint/migrations.py index 0ad57cd..44779e6 100644 --- a/cashu/mint/migrations.py +++ b/cashu/mint/migrations.py @@ -2,19 +2,16 @@ from ..core.db import Database, table_with_schema async def m000_create_migrations_table(db: Database): - await db.execute( - f""" + await db.execute(f""" CREATE TABLE IF NOT EXISTS {table_with_schema(db, 'dbversions')} ( db TEXT PRIMARY KEY, version INT NOT NULL ) - """ - ) + """) async def m001_initial(db: Database): - await db.execute( - f""" + await db.execute(f""" CREATE TABLE IF NOT EXISTS {table_with_schema(db, 'promises')} ( amount {db.big_int} NOT NULL, B_b TEXT NOT NULL, @@ -23,11 +20,9 @@ async def m001_initial(db: Database): UNIQUE (B_b) ); - """ - ) + """) - await db.execute( - f""" + await db.execute(f""" CREATE TABLE IF NOT EXISTS {table_with_schema(db, 'proofs_used')} ( amount {db.big_int} NOT NULL, C TEXT NOT NULL, @@ -36,11 +31,9 @@ async def m001_initial(db: Database): UNIQUE (secret) ); - """ - ) + """) - await db.execute( - f""" + await db.execute(f""" CREATE TABLE IF NOT EXISTS {table_with_schema(db, 'invoices')} ( amount {db.big_int} NOT NULL, pr TEXT NOT NULL, @@ -50,49 +43,41 @@ async def m001_initial(db: Database): UNIQUE (hash) ); - """ - ) + """) - await db.execute( - f""" + await db.execute(f""" CREATE VIEW {table_with_schema(db, 'balance_issued')} AS SELECT COALESCE(SUM(s), 0) AS balance FROM ( SELECT SUM(amount) FROM {table_with_schema(db, 'promises')} WHERE amount > 0 ) AS s; - """ - ) + """) - await db.execute( - f""" + await db.execute(f""" CREATE VIEW {table_with_schema(db, 'balance_redeemed')} AS SELECT COALESCE(SUM(s), 0) AS balance FROM ( SELECT SUM(amount) FROM {table_with_schema(db, 'proofs_used')} WHERE amount > 0 ) AS s; - """ - ) + """) - await db.execute( - f""" + await db.execute(f""" CREATE VIEW {table_with_schema(db, 'balance')} AS SELECT s_issued - s_used FROM ( SELECT bi.balance AS s_issued, bu.balance AS s_used FROM {table_with_schema(db, 'balance_issued')} bi CROSS JOIN {table_with_schema(db, 'balance_redeemed')} bu ) AS balance; - """ - ) + """) async def m003_mint_keysets(db: Database): """ Stores mint keysets from different mints and epochs. """ - await db.execute( - f""" + await db.execute(f""" CREATE TABLE IF NOT EXISTS {table_with_schema(db, 'keysets')} ( id TEXT NOT NULL, derivation_path TEXT, @@ -104,10 +89,8 @@ async def m003_mint_keysets(db: Database): UNIQUE (derivation_path) ); - """ - ) - await db.execute( - f""" + """) + await db.execute(f""" CREATE TABLE IF NOT EXISTS {table_with_schema(db, 'mint_pubkeys')} ( id TEXT NOT NULL, amount INTEGER NOT NULL, @@ -116,8 +99,7 @@ async def m003_mint_keysets(db: Database): UNIQUE (id, pubkey) ); - """ - ) + """) async def m004_keysets_add_version(db: Database): @@ -133,8 +115,7 @@ async def m005_pending_proofs_table(db: Database) -> None: """ Store pending proofs. """ - await db.execute( - f""" + await db.execute(f""" CREATE TABLE IF NOT EXISTS {table_with_schema(db, 'proofs_pending')} ( amount INTEGER NOT NULL, C TEXT NOT NULL, @@ -143,8 +124,7 @@ async def m005_pending_proofs_table(db: Database) -> None: UNIQUE (secret) ); - """ - ) + """) async def m006_invoices_add_payment_hash(db: Database): diff --git a/cashu/mint/router.py b/cashu/mint/router.py index 2fbb833..3ede2c6 100644 --- a/cashu/mint/router.py +++ b/cashu/mint/router.py @@ -59,7 +59,10 @@ async def info() -> GetInfoResponse: "/keys", name="Mint public keys", summary="Get the public keys of the newest mint keyset", - response_description="A dictionary of all supported token values of the mint and their associated public key of the current keyset.", + response_description=( + "A dictionary of all supported token values of the mint and their associated" + " public key of the current keyset." + ), response_model=KeysResponse, ) async def keys(): @@ -74,7 +77,10 @@ async def keys(): "/keys/{idBase64Urlsafe}", name="Keyset public keys", summary="Public keys of a specific keyset", - response_description="A dictionary of all supported token values of the mint and their associated public key for a specific keyset.", + response_description=( + "A dictionary of all supported token values of the mint and their associated" + " public key for a specific keyset." + ), response_model=KeysResponse, ) async def keyset_keys(idBase64Urlsafe: str): @@ -109,7 +115,10 @@ async def keysets() -> KeysetsResponse: name="Request mint", summary="Request minting of new tokens", response_model=GetMintResponse, - response_description="A Lightning invoice to be paid and a hash to request minting of new tokens after payment.", + response_description=( + "A Lightning invoice to be paid and a hash to request minting of new tokens" + " after payment." + ), ) async def request_mint(amount: int = 0) -> GetMintResponse: """ @@ -135,7 +144,9 @@ async def request_mint(amount: int = 0) -> GetMintResponse: name="Mint tokens", summary="Mint tokens in exchange for a Bitcoin paymemt that the user has made", response_model=PostMintResponse, - response_description="A list of blinded signatures that can be used to create proofs.", + response_description=( + "A list of blinded signatures that can be used to create proofs." + ), ) async def mint( payload: PostMintRequest, @@ -163,9 +174,15 @@ async def mint( @router.post( "/melt", name="Melt tokens", - summary="Melt tokens for a Bitcoin payment that the mint will make for the user in exchange", + summary=( + "Melt tokens for a Bitcoin payment that the mint will make for the user in" + " exchange" + ), response_model=GetMeltResponse, - response_description="The state of the payment, a preimage as proof of payment, and a list of promises for change.", + response_description=( + "The state of the payment, a preimage as proof of payment, and a list of" + " promises for change." + ), ) async def melt(payload: PostMeltRequest) -> GetMeltResponse: """ @@ -225,7 +242,9 @@ async def check_fees(payload: CheckFeesRequest) -> CheckFeesResponse: name="Split", summary="Split proofs at a specified amount", response_model=Union[PostSplitResponse, PostSplitResponse_Deprecated], - response_description="A list of blinded signatures that can be used to create proofs.", + response_description=( + "A list of blinded signatures that can be used to create proofs." + ), ) async def split( payload: PostSplitRequest, @@ -259,8 +278,9 @@ async def split( else: frst_promises.insert(0, promise) # and insert at the beginning logger.trace( - f"Split into keep: {len(frst_promises)}: {sum([p.amount for p in frst_promises])} " - f"sat and send: {len(scnd_promises)}: {sum([p.amount for p in scnd_promises])} sat" + f"Split into keep: {len(frst_promises)}:" + f" {sum([p.amount for p in frst_promises])} sat and send:" + f" {len(scnd_promises)}: {sum([p.amount for p in scnd_promises])} sat" ) return PostSplitResponse_Deprecated(fst=frst_promises, snd=scnd_promises) # END backwards compatibility < 0.13 diff --git a/cashu/mint/startup.py b/cashu/mint/startup.py index f4c8de7..735f59e 100644 --- a/cashu/mint/startup.py +++ b/cashu/mint/startup.py @@ -53,7 +53,8 @@ async def start_mint_init(): error_message, balance = await ledger.lightning.status() if error_message: logger.warning( - f"The backend for {ledger.lightning.__class__.__name__} isn't working properly: '{error_message}'", + f"The backend for {ledger.lightning.__class__.__name__} isn't working" + f" properly: '{error_message}'", RuntimeWarning, ) logger.info(f"Lightning balance: {balance} msat") diff --git a/cashu/wallet/api/router.py b/cashu/wallet/api/router.py index 7ad7e9d..3a671b6 100644 --- a/cashu/wallet/api/router.py +++ b/cashu/wallet/api/router.py @@ -276,8 +276,9 @@ async def burn( wallet = await mint_wallet(mint) if not (all or token or force or delete) or (token and all): raise Exception( - "enter a token or use --all to burn all pending tokens, --force to check all tokens" - "or --delete with send ID to force-delete pending token from list if mint is unavailable.", + "enter a token or use --all to burn all pending tokens, --force to check" + " all tokensor --delete with send ID to force-delete pending token from" + " list if mint is unavailable.", ) if all: # check only those who are flagged as reserved diff --git a/cashu/wallet/cli/cli.py b/cashu/wallet/cli/cli.py index c3e6b37..9acf2b2 100644 --- a/cashu/wallet/cli/cli.py +++ b/cashu/wallet/cli/cli.py @@ -90,18 +90,27 @@ def coro(f): async def cli(ctx: Context, host: str, walletname: str, tests: bool): if settings.tor and not TorProxy().check_platform(): error_str = ( - "Your settings say TOR=true but the built-in Tor bundle is not supported on your system. You have two options: Either install" - " Tor manually and set TOR=FALSE and SOCKS_HOST=localhost and SOCKS_PORT=9050 in your Cashu config (recommended). Or turn off Tor by " - "setting TOR=false (not recommended). Cashu will not work until you edit your config file accordingly." + "Your settings say TOR=true but the built-in Tor bundle is not supported on" + " your system. You have two options: Either install Tor manually and set" + " TOR=FALSE and SOCKS_HOST=localhost and SOCKS_PORT=9050 in your Cashu" + " config (recommended). Or turn off Tor by setting TOR=false (not" + " recommended). Cashu will not work until you edit your config file" + " accordingly." ) error_str += "\n\n" if settings.env_file: error_str += f"Edit your Cashu config file here: {settings.env_file}" env_path = settings.env_file else: - error_str += f"Ceate a new Cashu config file here: {os.path.join(settings.cashu_dir, '.env')}" + error_str += ( + "Ceate a new Cashu config file here:" + f" {os.path.join(settings.cashu_dir, '.env')}" + ) env_path = os.path.join(settings.cashu_dir, ".env") - error_str += f'\n\nYou can turn off Tor with this command: echo "TOR=FALSE" >> {env_path}' + error_str += ( + '\n\nYou can turn off Tor with this command: echo "TOR=FALSE" >>' + f" {env_path}" + ) raise Exception(error_str) ctx.ensure_object(dict) @@ -155,7 +164,8 @@ async def pay(ctx: Context, invoice: str, yes: bool): total_amount, fee_reserve_sat = await wallet.get_pay_amount_with_fees(invoice) if not yes: click.confirm( - f"Pay {total_amount - fee_reserve_sat} sat ({total_amount} sat with potential fees)?", + f"Pay {total_amount - fee_reserve_sat} sat ({total_amount} sat with" + " potential fees)?", abort=True, default=True, ) @@ -206,7 +216,8 @@ async def invoice(ctx: Context, amount: int, hash: str, split: int): print(f"Invoice: {invoice.pr}") print("") print( - f"If you abort this you can use this command to recheck the invoice:\ncashu invoice {amount} --hash {invoice.hash}" + "If you abort this you can use this command to recheck the" + f" invoice:\ncashu invoice {amount} --hash {invoice.hash}" ) check_until = time.time() + 5 * 60 # check for five minutes print("") @@ -232,7 +243,8 @@ async def invoice(ctx: Context, amount: int, hash: str, split: int): if not paid: print("\n") print( - "Invoice is not paid yet, stopping check. Use the command above to recheck after the invoice has been paid." + "Invoice is not paid yet, stopping check. Use the command above to" + " recheck after the invoice has been paid." ) # user paid invoice and want to check it @@ -306,7 +318,8 @@ async def balance(ctx: Context, verbose): print("") for k, v in keyset_balances.items(): print( - f"Keyset: {k} - Balance: {v['available']} sat (pending: {v['balance']-v['available']} sat)" + f"Keyset: {k} - Balance: {v['available']} sat (pending:" + f" {v['balance']-v['available']} sat)" ) print("") @@ -314,8 +327,9 @@ async def balance(ctx: Context, verbose): if verbose: print( - f"Balance: {wallet.available_balance} sat (pending: {wallet.balance-wallet.available_balance} sat) " - f"in {len([p for p in wallet.proofs if not p.reserved])} tokens" + f"Balance: {wallet.available_balance} sat (pending:" + f" {wallet.balance-wallet.available_balance} sat) in" + f" {len([p for p in wallet.proofs if not p.reserved])} tokens" ) else: print(f"Balance: {wallet.available_balance} sat") @@ -386,7 +400,7 @@ async def send_command( "-n", default=False, is_flag=True, - help="Receive tokens via nostr." "receive", + help="Receive tokens via nostr.receive", ) @click.option( "--all", "-a", default=False, is_flag=True, help="Receive all pending tokens." @@ -454,8 +468,9 @@ async def burn(ctx: Context, token: str, all: bool, force: bool, delete: str): await wallet.load_mint() if not (all or token or force or delete) or (token and all): print( - "Error: enter a token or use --all to burn all pending tokens, --force to check all tokens " - "or --delete with send ID to force-delete pending token from list if mint is unavailable." + "Error: enter a token or use --all to burn all pending tokens, --force to" + " check all tokens or --delete with send ID to force-delete pending token" + " from list if mint is unavailable." ) return if all: @@ -527,7 +542,8 @@ async def pending(ctx: Context, legacy, number: int, offset: int): int(grouped_proofs[0].time_reserved) ).strftime("%Y-%m-%d %H:%M:%S") print( - f"#{i} Amount: {sum_proofs(grouped_proofs)} sat Time: {reserved_date} ID: {key} Mint: {mint}\n" + f"#{i} Amount: {sum_proofs(grouped_proofs)} sat Time:" + f" {reserved_date} ID: {key} Mint: {mint}\n" ) print(f"{token}\n") @@ -657,7 +673,8 @@ async def wallets(ctx): if w == ctx.obj["WALLET_NAME"]: active_wallet = True print( - f"Wallet: {w}\tBalance: {sum_proofs(wallet.proofs)} sat (available: " + f"Wallet: {w}\tBalance: {sum_proofs(wallet.proofs)} sat" + " (available: " f"{sum_proofs([p for p in wallet.proofs if not p.reserved])} sat){' *' if active_wallet else ''}" ) except Exception: @@ -741,12 +758,14 @@ async def restore(ctx: Context, to: int, batch: int): ret = await get_seed_and_mnemonic(wallet.db) if ret: print( - "Wallet already has a mnemonic. You can't restore an already initialized wallet." + "Wallet already has a mnemonic. You can't restore an already initialized" + " wallet." ) print("To restore a wallet, please delete the wallet directory and try again.") print("") print( - f"The wallet directory is: {os.path.join(settings.cashu_dir, ctx.obj['WALLET_NAME'])}" + "The wallet directory is:" + f" {os.path.join(settings.cashu_dir, ctx.obj['WALLET_NAME'])}" ) return # ask the user for a mnemonic but allow also no input diff --git a/cashu/wallet/cli/cli_helpers.py b/cashu/wallet/cli/cli_helpers.py index 068d244..e7d12b2 100644 --- a/cashu/wallet/cli/cli_helpers.py +++ b/cashu/wallet/cli/cli_helpers.py @@ -78,7 +78,8 @@ async def print_mint_balances(wallet, show_mints=False): print("") for i, (k, v) in enumerate(mint_balances.items()): print( - f"Mint {i+1}: Balance: {v['available']} sat (pending: {v['balance']-v['available']} sat) URL: {k}" + f"Mint {i+1}: Balance: {v['available']} sat (pending:" + f" {v['balance']-v['available']} sat) URL: {k}" ) print("") diff --git a/cashu/wallet/crud.py b/cashu/wallet/crud.py index 887db75..e229ccf 100644 --- a/cashu/wallet/crud.py +++ b/cashu/wallet/crud.py @@ -31,11 +31,9 @@ async def get_proofs( db: Database, conn: Optional[Connection] = None, ): - rows = await (conn or db).fetchall( - """ + rows = await (conn or db).fetchall(""" SELECT * from proofs - """ - ) + """) return [Proof(**dict(r)) for r in rows] @@ -43,12 +41,10 @@ async def get_reserved_proofs( db: Database, conn: Optional[Connection] = None, ): - rows = await (conn or db).fetchall( - """ + rows = await (conn or db).fetchall(""" SELECT * from proofs WHERE reserved - """ - ) + """) return [Proof(**r) for r in rows] diff --git a/cashu/wallet/helpers.py b/cashu/wallet/helpers.py index ac71118..302298d 100644 --- a/cashu/wallet/helpers.py +++ b/cashu/wallet/helpers.py @@ -195,7 +195,8 @@ async def send( send_proofs = [p] break assert send_proofs, Exception( - f"No proof with this amount found. Available amounts: {set([p.amount for p in wallet.proofs])}" + "No proof with this amount found. Available amounts:" + f" {set([p.amount for p in wallet.proofs])}" ) await wallet.set_reserved(send_proofs, reserved=True) diff --git a/cashu/wallet/migrations.py b/cashu/wallet/migrations.py index 810def7..061b31c 100644 --- a/cashu/wallet/migrations.py +++ b/cashu/wallet/migrations.py @@ -2,19 +2,16 @@ from ..core.db import Database async def m000_create_migrations_table(db: Database): - await db.execute( - """ + await db.execute(""" CREATE TABLE IF NOT EXISTS dbversions ( db TEXT PRIMARY KEY, version INT NOT NULL ) - """ - ) + """) async def m001_initial(db: Database): - await db.execute( - f""" + await db.execute(f""" CREATE TABLE IF NOT EXISTS proofs ( amount {db.big_int} NOT NULL, C TEXT NOT NULL, @@ -23,11 +20,9 @@ async def m001_initial(db: Database): UNIQUE (secret) ); - """ - ) + """) - await db.execute( - f""" + await db.execute(f""" CREATE TABLE IF NOT EXISTS proofs_used ( amount {db.big_int} NOT NULL, C TEXT NOT NULL, @@ -36,30 +31,25 @@ async def m001_initial(db: Database): UNIQUE (secret) ); - """ - ) + """) - await db.execute( - """ + await db.execute(""" CREATE VIEW IF NOT EXISTS balance AS SELECT COALESCE(SUM(s), 0) AS balance FROM ( SELECT SUM(amount) AS s FROM proofs WHERE amount > 0 ); - """ - ) + """) - await db.execute( - """ + await db.execute(""" CREATE VIEW IF NOT EXISTS balance_used AS SELECT COALESCE(SUM(s), 0) AS used FROM ( SELECT SUM(amount) AS s FROM proofs_used WHERE amount > 0 ); - """ - ) + """) async def m002_add_proofs_reserved(db: Database): @@ -85,8 +75,7 @@ async def m004_p2sh_locks(db: Database): """ Stores P2SH addresses and unlock scripts. """ - await db.execute( - """ + await db.execute(""" CREATE TABLE IF NOT EXISTS p2sh ( address TEXT NOT NULL, script TEXT NOT NULL, @@ -96,16 +85,14 @@ async def m004_p2sh_locks(db: Database): UNIQUE (address, script, signature) ); - """ - ) + """) async def m005_wallet_keysets(db: Database): """ Stores mint keysets from different mints and epochs. """ - await db.execute( - f""" + await db.execute(f""" CREATE TABLE IF NOT EXISTS keysets ( id TEXT, mint_url TEXT, @@ -117,8 +104,7 @@ async def m005_wallet_keysets(db: Database): UNIQUE (id, mint_url) ); - """ - ) + """) await db.execute("ALTER TABLE proofs ADD COLUMN id TEXT") await db.execute("ALTER TABLE proofs_used ADD COLUMN id TEXT") @@ -128,8 +114,7 @@ async def m006_invoices(db: Database): """ Stores Lightning invoices. """ - await db.execute( - f""" + await db.execute(f""" CREATE TABLE IF NOT EXISTS invoices ( amount INTEGER NOT NULL, pr TEXT NOT NULL, @@ -142,22 +127,19 @@ async def m006_invoices(db: Database): UNIQUE (hash) ); - """ - ) + """) async def m007_nostr(db: Database): """ Stores timestamps of nostr operations. """ - await db.execute( - """ + await db.execute(""" CREATE TABLE IF NOT EXISTS nostr ( type TEXT NOT NULL, last TIMESTAMP DEFAULT NULL ) - """ - ) + """) await db.execute( """ INSERT INTO nostr @@ -182,14 +164,12 @@ async def m009_privatekey_and_determinstic_key_derivation(db: Database): await db.execute("ALTER TABLE keysets ADD COLUMN counter INTEGER DEFAULT 0") await db.execute("ALTER TABLE proofs ADD COLUMN derivation_path TEXT") await db.execute("ALTER TABLE proofs_used ADD COLUMN derivation_path TEXT") - await db.execute( - """ + await db.execute(""" CREATE TABLE IF NOT EXISTS seed ( seed TEXT NOT NULL, mnemonic TEXT NOT NULL, UNIQUE (seed, mnemonic) ); - """ - ) + """) # await db.execute("INSERT INTO secret_derivation (counter) VALUES (0)") diff --git a/cashu/wallet/nostr.py b/cashu/wallet/nostr.py index 1ea1918..3f508b7 100644 --- a/cashu/wallet/nostr.py +++ b/cashu/wallet/nostr.py @@ -99,8 +99,9 @@ async def receive_nostr( ): if settings.nostr_private_key is None: print( - "Warning: No nostr private key set! You don't have NOSTR_PRIVATE_KEY set in your .env file. " - "I will create a random private key for this session but I will not remember it." + "Warning: No nostr private key set! You don't have NOSTR_PRIVATE_KEY set in" + " your .env file. I will create a random private key for this session but I" + " will not remember it." ) print("") client = NostrClient( diff --git a/cashu/wallet/wallet.py b/cashu/wallet/wallet.py index 61cd606..8926ffa 100644 --- a/cashu/wallet/wallet.py +++ b/cashu/wallet/wallet.py @@ -702,7 +702,8 @@ class Wallet(LedgerAPI): else "" ) print( - f'Generated a new mnemonic{wallet_name}. To view it, run "cashu{wallet_command_prefix_str} info --mnemonic".' + f"Generated a new mnemonic{wallet_name}. To view it, run" + f' "cashu{wallet_command_prefix_str} info --mnemonic".' ) elif from_mnemonic: # or use the one provided @@ -1425,7 +1426,8 @@ class Wallet(LedgerAPI): if invalidated_proofs: logger.debug( - f"Invalidating {len(invalidated_proofs)} proofs worth {sum_proofs(invalidated_proofs)} sat." + f"Invalidating {len(invalidated_proofs)} proofs worth" + f" {sum_proofs(invalidated_proofs)} sat." ) async with self.db.connect() as conn: @@ -1559,7 +1561,8 @@ class Wallet(LedgerAPI): private_key = self.private_key assert private_key.pubkey logger.trace( - f"Signing with private key: {private_key.serialize()} public key: {private_key.pubkey.serialize().hex()}" + f"Signing with private key: {private_key.serialize()} public key:" + f" {private_key.pubkey.serialize().hex()}" ) for proof in proofs: logger.trace(f"Signing proof: {proof}") diff --git a/poetry.lock b/poetry.lock index ccdf37d..4a3bc9e 100644 --- a/poetry.lock +++ b/poetry.lock @@ -104,31 +104,42 @@ files = [ [[package]] name = "black" -version = "22.12.0" +version = "23.7.0" description = "The uncompromising code formatter." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "black-22.12.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9eedd20838bd5d75b80c9f5487dbcb06836a43833a37846cf1d8c1cc01cef59d"}, - {file = "black-22.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:159a46a4947f73387b4d83e87ea006dbb2337eab6c879620a3ba52699b1f4351"}, - {file = "black-22.12.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d30b212bffeb1e252b31dd269dfae69dd17e06d92b87ad26e23890f3efea366f"}, - {file = "black-22.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:7412e75863aa5c5411886804678b7d083c7c28421210180d67dfd8cf1221e1f4"}, - {file = "black-22.12.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c116eed0efb9ff870ded8b62fe9f28dd61ef6e9ddd28d83d7d264a38417dcee2"}, - {file = "black-22.12.0-cp37-cp37m-win_amd64.whl", hash = "sha256:1f58cbe16dfe8c12b7434e50ff889fa479072096d79f0a7f25e4ab8e94cd8350"}, - {file = "black-22.12.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77d86c9f3db9b1bf6761244bc0b3572a546f5fe37917a044e02f3166d5aafa7d"}, - {file = "black-22.12.0-cp38-cp38-win_amd64.whl", hash = "sha256:82d9fe8fee3401e02e79767016b4907820a7dc28d70d137eb397b92ef3cc5bfc"}, - {file = "black-22.12.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:101c69b23df9b44247bd88e1d7e90154336ac4992502d4197bdac35dd7ee3320"}, - {file = "black-22.12.0-cp39-cp39-win_amd64.whl", hash = "sha256:559c7a1ba9a006226f09e4916060982fd27334ae1998e7a38b3f33a37f7a2148"}, - {file = "black-22.12.0-py3-none-any.whl", hash = "sha256:436cc9167dd28040ad90d3b404aec22cedf24a6e4d7de221bec2730ec0c97bcf"}, - {file = "black-22.12.0.tar.gz", hash = "sha256:229351e5a18ca30f447bf724d007f890f97e13af070bb6ad4c0a441cd7596a2f"}, + {file = "black-23.7.0-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:5c4bc552ab52f6c1c506ccae05681fab58c3f72d59ae6e6639e8885e94fe2587"}, + {file = "black-23.7.0-cp310-cp310-macosx_10_16_universal2.whl", hash = "sha256:552513d5cd5694590d7ef6f46e1767a4df9af168d449ff767b13b084c020e63f"}, + {file = "black-23.7.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:86cee259349b4448adb4ef9b204bb4467aae74a386bce85d56ba4f5dc0da27be"}, + {file = "black-23.7.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:501387a9edcb75d7ae8a4412bb8749900386eaef258f1aefab18adddea1936bc"}, + {file = "black-23.7.0-cp310-cp310-win_amd64.whl", hash = "sha256:fb074d8b213749fa1d077d630db0d5f8cc3b2ae63587ad4116e8a436e9bbe995"}, + {file = "black-23.7.0-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:b5b0ee6d96b345a8b420100b7d71ebfdd19fab5e8301aff48ec270042cd40ac2"}, + {file = "black-23.7.0-cp311-cp311-macosx_10_16_universal2.whl", hash = "sha256:893695a76b140881531062d48476ebe4a48f5d1e9388177e175d76234ca247cd"}, + {file = "black-23.7.0-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:c333286dc3ddca6fdff74670b911cccedacb4ef0a60b34e491b8a67c833b343a"}, + {file = "black-23.7.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:831d8f54c3a8c8cf55f64d0422ee875eecac26f5f649fb6c1df65316b67c8926"}, + {file = "black-23.7.0-cp311-cp311-win_amd64.whl", hash = "sha256:7f3bf2dec7d541b4619b8ce526bda74a6b0bffc480a163fed32eb8b3c9aed8ad"}, + {file = "black-23.7.0-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:f9062af71c59c004cd519e2fb8f5d25d39e46d3af011b41ab43b9c74e27e236f"}, + {file = "black-23.7.0-cp38-cp38-macosx_10_16_universal2.whl", hash = "sha256:01ede61aac8c154b55f35301fac3e730baf0c9cf8120f65a9cd61a81cfb4a0c3"}, + {file = "black-23.7.0-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:327a8c2550ddc573b51e2c352adb88143464bb9d92c10416feb86b0f5aee5ff6"}, + {file = "black-23.7.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d1c6022b86f83b632d06f2b02774134def5d4d4f1dac8bef16d90cda18ba28a"}, + {file = "black-23.7.0-cp38-cp38-win_amd64.whl", hash = "sha256:27eb7a0c71604d5de083757fbdb245b1a4fae60e9596514c6ec497eb63f95320"}, + {file = "black-23.7.0-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:8417dbd2f57b5701492cd46edcecc4f9208dc75529bcf76c514864e48da867d9"}, + {file = "black-23.7.0-cp39-cp39-macosx_10_16_universal2.whl", hash = "sha256:47e56d83aad53ca140da0af87678fb38e44fd6bc0af71eebab2d1f59b1acf1d3"}, + {file = "black-23.7.0-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:25cc308838fe71f7065df53aedd20327969d05671bac95b38fdf37ebe70ac087"}, + {file = "black-23.7.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:642496b675095d423f9b8448243336f8ec71c9d4d57ec17bf795b67f08132a91"}, + {file = "black-23.7.0-cp39-cp39-win_amd64.whl", hash = "sha256:ad0014efc7acf0bd745792bd0d8857413652979200ab924fbf239062adc12491"}, + {file = "black-23.7.0-py3-none-any.whl", hash = "sha256:9fd59d418c60c0348505f2ddf9609c1e1de8e7493eab96198fc89d9f865e7a96"}, + {file = "black-23.7.0.tar.gz", hash = "sha256:022a582720b0d9480ed82576c920a8c1dde97cc38ff11d8d8859b3bd6ca9eedb"}, ] [package.dependencies] click = ">=8.0.0" mypy-extensions = ">=0.4.3" +packaging = ">=22.0" pathspec = ">=0.9.0" platformdirs = ">=2" -tomli = {version = ">=1.1.0", markers = "python_full_version < \"3.11.0a7\""} +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} typing-extensions = {version = ">=3.10.0.0", markers = "python_version < \"3.10\""} [package.extras] @@ -614,22 +625,6 @@ files = [ docs = ["furo (>=2023.5.20)", "sphinx (>=7.0.1)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"] testing = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "diff-cover (>=7.5)", "pytest (>=7.3.1)", "pytest-cov (>=4.1)", "pytest-mock (>=3.10)", "pytest-timeout (>=2.1)"] -[[package]] -name = "flake8" -version = "6.0.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"}, -] - -[package.dependencies] -mccabe = ">=0.7.0,<0.8.0" -pycodestyle = ">=2.10.0,<2.11.0" -pyflakes = ">=3.0.0,<3.1.0" - [[package]] name = "h11" version = "0.12.0" @@ -740,23 +735,6 @@ files = [ {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, ] -[[package]] -name = "isort" -version = "5.12.0" -description = "A Python utility / library to sort Python imports." -optional = false -python-versions = ">=3.8.0" -files = [ - {file = "isort-5.12.0-py3-none-any.whl", hash = "sha256:f84c2818376e66cf843d497486ea8fed8700b340f308f076c6fb1229dff318b6"}, - {file = "isort-5.12.0.tar.gz", hash = "sha256:8bef7dde241278824a6d83f44a544709b065191b95b6e50894bdc722fcba0504"}, -] - -[package.extras] -colors = ["colorama (>=0.4.3)"] -pipfile-deprecated-finder = ["pip-shims (>=0.5.2)", "pipreqs", "requirementslib"] -plugins = ["setuptools"] -requirements-deprecated-finder = ["pip-api", "pipreqs"] - [[package]] name = "loguru" version = "0.6.0" @@ -795,17 +773,6 @@ docs = ["alabaster (==0.7.13)", "autodocsumm (==0.2.11)", "sphinx (==7.0.1)", "s lint = ["flake8 (==6.0.0)", "flake8-bugbear (==23.7.10)", "mypy (==1.4.1)", "pre-commit (>=2.4,<4.0)"] tests = ["pytest", "pytz", "simplejson"] -[[package]] -name = "mccabe" -version = "0.7.0" -description = "McCabe checker, plugin for flake8" -optional = false -python-versions = ">=3.6" -files = [ - {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, - {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, -] - [[package]] name = "mnemonic" version = "0.20" @@ -1039,17 +1006,6 @@ files = [ {file = "psycopg2_binary-2.9.6-cp39-cp39-win_amd64.whl", hash = "sha256:f6a88f384335bb27812293fdb11ac6aee2ca3f51d3c7820fe03de0a304ab6249"}, ] -[[package]] -name = "pycodestyle" -version = "2.10.0" -description = "Python style guide checker" -optional = false -python-versions = ">=3.6" -files = [ - {file = "pycodestyle-2.10.0-py2.py3-none-any.whl", hash = "sha256:8a4eaf0d0495c7395bdab3589ac2db602797d76207242c17d470186815706610"}, - {file = "pycodestyle-2.10.0.tar.gz", hash = "sha256:347187bdb476329d98f695c213d7295a846d1152ff4fe9bacb8a9590b8ee7053"}, -] - [[package]] name = "pycparser" version = "2.21" @@ -1154,17 +1110,6 @@ typing-extensions = ">=4.2.0" dotenv = ["python-dotenv (>=0.10.4)"] email = ["email-validator (>=1.0.3)"] -[[package]] -name = "pyflakes" -version = "3.0.1" -description = "passive checker of Python programs" -optional = false -python-versions = ">=3.6" -files = [ - {file = "pyflakes-3.0.1-py2.py3-none-any.whl", hash = "sha256:ec55bf7fe21fff7f1ad2f7da62363d749e2a470500eab1b555334b67aa1ef8cf"}, - {file = "pyflakes-3.0.1.tar.gz", hash = "sha256:ec8b276a6b60bd80defed25add7e439881c19e64850afd9b346283d4165fd0fd"}, -] - [[package]] name = "pysocks" version = "1.7.1" @@ -1363,6 +1308,32 @@ idna = {version = "*", optional = true, markers = "extra == \"idna2008\""} [package.extras] idna2008 = ["idna"] +[[package]] +name = "ruff" +version = "0.0.284" +description = "An extremely fast Python linter, written in Rust." +optional = false +python-versions = ">=3.7" +files = [ + {file = "ruff-0.0.284-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:8b949084941232e2c27f8d12c78c5a6a010927d712ecff17231ee1a8371c205b"}, + {file = "ruff-0.0.284-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:a3930d66b35e4dc96197422381dff2a4e965e9278b5533e71ae8474ef202fab0"}, + {file = "ruff-0.0.284-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d1f7096038961d8bc3b956ee69d73826843eb5b39a5fa4ee717ed473ed69c95"}, + {file = "ruff-0.0.284-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bcaf85907fc905d838f46490ee15f04031927bbea44c478394b0bfdeadc27362"}, + {file = "ruff-0.0.284-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b3660b85a9d84162a055f1add334623ae2d8022a84dcd605d61c30a57b436c32"}, + {file = "ruff-0.0.284-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:0a3218458b140ea794da72b20ea09cbe13c4c1cdb7ac35e797370354628f4c05"}, + {file = "ruff-0.0.284-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b2fe880cff13fffd735387efbcad54ba0ff1272bceea07f86852a33ca71276f4"}, + {file = "ruff-0.0.284-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d1d098ea74d0ce31478765d1f8b4fbdbba2efc532397b5c5e8e5ea0c13d7e5ae"}, + {file = "ruff-0.0.284-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c4c79ae3308e308b94635cd57a369d1e6f146d85019da2fbc63f55da183ee29b"}, + {file = "ruff-0.0.284-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:f86b2b1e7033c00de45cc176cf26778650fb8804073a0495aca2f674797becbb"}, + {file = "ruff-0.0.284-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:e37e086f4d623c05cd45a6fe5006e77a2b37d57773aad96b7802a6b8ecf9c910"}, + {file = "ruff-0.0.284-py3-none-musllinux_1_2_i686.whl", hash = "sha256:d29dfbe314e1131aa53df213fdfea7ee874dd96ea0dd1471093d93b59498384d"}, + {file = "ruff-0.0.284-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:88295fd649d0aa1f1271441df75bf06266a199497afd239fd392abcfd75acd7e"}, + {file = "ruff-0.0.284-py3-none-win32.whl", hash = "sha256:735cd62fccc577032a367c31f6a9de7c1eb4c01fa9a2e60775067f44f3fc3091"}, + {file = "ruff-0.0.284-py3-none-win_amd64.whl", hash = "sha256:f67ed868d79fbcc61ad0fa034fe6eed2e8d438d32abce9c04b7c4c1464b2cf8e"}, + {file = "ruff-0.0.284-py3-none-win_arm64.whl", hash = "sha256:1292cfc764eeec3cde35b3a31eae3f661d86418b5e220f5d5dba1c27a6eccbb6"}, + {file = "ruff-0.0.284.tar.gz", hash = "sha256:ebd3cc55cd499d326aac17a331deaea29bea206e01c08862f9b5c6e93d77a491"}, +] + [[package]] name = "secp256k1" version = "0.14.0" @@ -1672,4 +1643,4 @@ pgsql = ["psycopg2-binary"] [metadata] lock-version = "2.0" python-versions = "^3.8.1" -content-hash = "7bc36d84b841a4799da7a9f631d90195a569d3bf38dd5b4a7ed47a5901940d88" +content-hash = "83e8f09ebad4bca75c90591fbe0c50d0acf9d19edf6e30437e91fded95cd88c4" diff --git a/pyproject.toml b/pyproject.toml index ee79539..e3a5847 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -39,13 +39,12 @@ pgsql = ["psycopg2-binary"] [tool.poetry.group.dev.dependencies] mypy = "^0.971" -black = {version = "^22.8.0", allow-prereleases = true} -isort = "^5.10.1" pytest-asyncio = "^0.19.0" pytest-cov = "^4.0.0" pytest = "^7.4.0" -flake8 = "^6.0.0" pre-commit = "^3.3.3" +ruff = "^0.0.284" +black = "^23.7.0" [build-system] requires = ["poetry-core>=1.0.0"] @@ -55,3 +54,62 @@ build-backend = "poetry.core.masonry.api" mint = "cashu.mint.main:main" cashu = "cashu.wallet.cli.cli:cli" wallet-test = "tests.test_wallet:test" + + +[tool.black] +line-length = 88 + +# previously experimental-string-processing = true +# this should autoformat string properly but does not work +preview = true + + +[tool.ruff] +# Same as Black. but black has a 10% overflow rule +line-length = 150 + +# Enable pycodestyle (`E`) and Pyflakes (`F`) codes by default. +# (`I`) means isorting +select = ["E", "F", "I"] +ignore = [] + +# Allow autofix for all enabled rules (when `--fix`) is provided. +fixable = ["ALL"] +unfixable = [] + +# Exclude a variety of commonly ignored directories. +exclude = [ + "cashu/nostr", + "cashu/core/bolt11.py", + ".bzr", + ".direnv", + ".eggs", + ".git", + ".git-rewrite", + ".hg", + ".mypy_cache", + ".nox", + ".pants.d", + ".pytype", + ".ruff_cache", + ".svn", + ".tox", + ".venv", + "__pypackages__", + "_build", + "buck-out", + "build", + "dist", + "node_modules", + "venv", +] + +# Allow unused variables when underscore-prefixed. +dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$" + +# Assume Python 3.8 +# target-version = "py38" + +[tool.ruff.mccabe] +# Unlike Flake8, default to a complexity level of 10. +max-complexity = 10 diff --git a/tests/test_wallet.py b/tests/test_wallet.py index dc2d850..c33eee1 100644 --- a/tests/test_wallet.py +++ b/tests/test_wallet.py @@ -94,7 +94,7 @@ async def test_get_keys(wallet1: Wallet): assert len(wallet1.keys.public_keys) == settings.max_order keyset = await wallet1._get_keys(wallet1.url) assert keyset.id is not None - assert type(keyset.id) == str + assert isinstance(keyset.id, str) assert len(keyset.id) > 0 @@ -244,9 +244,7 @@ async def test_duplicate_proofs_double_spent(wallet1: Wallet): @pytest.mark.asyncio async def test_send_and_redeem(wallet1: Wallet, wallet2: Wallet): await wallet1.mint(64) - _, spendable_proofs = await wallet1.split_to_send( # type: ignore - wallet1.proofs, 32, set_reserved=True - ) + _, spendable_proofs = await wallet1.split_to_send(wallet1.proofs, 32, set_reserved=True) # type: ignore await wallet2.redeem(spendable_proofs) assert wallet2.balance == 32 @@ -325,7 +323,8 @@ async def test_token_state(wallet1: Wallet): @pytest.mark.asyncio async def test_bump_secret_derivation(wallet3: Wallet): await wallet3._init_private_key( - "half depart obvious quality work element tank gorilla view sugar picture humble" + "half depart obvious quality work element tank gorilla view sugar picture" + " humble" ) secrets1, rs1, derivaion_paths1 = await wallet3.generate_n_secrets(5) secrets2, rs2, derivaion_paths2 = await wallet3.generate_secrets_from_to(0, 4) @@ -351,7 +350,8 @@ async def test_bump_secret_derivation(wallet3: Wallet): @pytest.mark.asyncio async def test_bump_secret_derivation_two_steps(wallet3: Wallet): await wallet3._init_private_key( - "half depart obvious quality work element tank gorilla view sugar picture humble" + "half depart obvious quality work element tank gorilla view sugar picture" + " humble" ) secrets1_1, rs1_1, derivaion_paths1 = await wallet3.generate_n_secrets(2) secrets1_2, rs1_2, derivaion_paths2 = await wallet3.generate_n_secrets(3) @@ -365,7 +365,8 @@ async def test_bump_secret_derivation_two_steps(wallet3: Wallet): @pytest.mark.asyncio async def test_generate_secrets_from_to(wallet3: Wallet): await wallet3._init_private_key( - "half depart obvious quality work element tank gorilla view sugar picture humble" + "half depart obvious quality work element tank gorilla view sugar picture" + " humble" ) secrets1, rs1, derivaion_paths1 = await wallet3.generate_secrets_from_to(0, 4) assert len(secrets1) == 5 @@ -392,7 +393,8 @@ async def test_restore_wallet_after_mint(wallet3: Wallet): async def test_restore_wallet_with_invalid_mnemonic(wallet3: Wallet): await assert_err( wallet3._init_private_key( - "half depart obvious quality work element tank gorilla view sugar picture picture" + "half depart obvious quality work element tank gorilla view sugar picture" + " picture" ), "Invalid mnemonic", ) @@ -401,16 +403,15 @@ async def test_restore_wallet_with_invalid_mnemonic(wallet3: Wallet): @pytest.mark.asyncio async def test_restore_wallet_after_split_to_send(wallet3: Wallet): await wallet3._init_private_key( - "half depart obvious quality work element tank gorilla view sugar picture humble" + "half depart obvious quality work element tank gorilla view sugar picture" + " humble" ) await reset_wallet_db(wallet3) await wallet3.mint(64) assert wallet3.balance == 64 - _, spendable_proofs = await wallet3.split_to_send( # type: ignore - wallet3.proofs, 32, set_reserved=True - ) + _, spendable_proofs = await wallet3.split_to_send(wallet3.proofs, 32, set_reserved=True) # type: ignore await reset_wallet_db(wallet3) await wallet3.load_proofs() @@ -432,9 +433,7 @@ async def test_restore_wallet_after_send_and_receive(wallet3: Wallet, wallet2: W await wallet3.mint(64) assert wallet3.balance == 64 - _, spendable_proofs = await wallet3.split_to_send( # type: ignore - wallet3.proofs, 32, set_reserved=True - ) + _, spendable_proofs = await wallet3.split_to_send(wallet3.proofs, 32, set_reserved=True) # type: ignore await wallet2.redeem(spendable_proofs) @@ -465,16 +464,15 @@ class ProofBox: @pytest.mark.asyncio async def test_restore_wallet_after_send_and_self_receive(wallet3: Wallet): await wallet3._init_private_key( - "lucky broken tell exhibit shuffle tomato ethics virus rabbit spread measure text" + "lucky broken tell exhibit shuffle tomato ethics virus rabbit spread measure" + " text" ) await reset_wallet_db(wallet3) await wallet3.mint(64) assert wallet3.balance == 64 - _, spendable_proofs = await wallet3.split_to_send( # type: ignore - wallet3.proofs, 32, set_reserved=True - ) + _, spendable_proofs = await wallet3.split_to_send(wallet3.proofs, 32, set_reserved=True) # type: ignore await wallet3.redeem(spendable_proofs) @@ -500,9 +498,7 @@ async def test_restore_wallet_after_send_twice( box.add(wallet3.proofs) assert wallet3.balance == 2 - keep_proofs, spendable_proofs = await wallet3.split_to_send( # type: ignore - wallet3.proofs, 1, set_reserved=True - ) + keep_proofs, spendable_proofs = await wallet3.split_to_send(wallet3.proofs, 1, set_reserved=True) # type: ignore box.add(wallet3.proofs) assert wallet3.available_balance == 1 await wallet3.redeem(spendable_proofs) @@ -522,9 +518,7 @@ async def test_restore_wallet_after_send_twice( # again - _, spendable_proofs = await wallet3.split_to_send( # type: ignore - wallet3.proofs, 1, set_reserved=True - ) + _, spendable_proofs = await wallet3.split_to_send(wallet3.proofs, 1, set_reserved=True) # type: ignore box.add(wallet3.proofs) assert wallet3.available_balance == 1 @@ -557,9 +551,7 @@ async def test_restore_wallet_after_send_and_self_receive_nonquadratic_value( box.add(wallet3.proofs) assert wallet3.balance == 64 - keep_proofs, spendable_proofs = await wallet3.split_to_send( # type: ignore - wallet3.proofs, 10, set_reserved=True - ) + keep_proofs, spendable_proofs = await wallet3.split_to_send(wallet3.proofs, 10, set_reserved=True) # type: ignore box.add(wallet3.proofs) assert wallet3.available_balance == 64 - 10 @@ -579,9 +571,7 @@ async def test_restore_wallet_after_send_and_self_receive_nonquadratic_value( # again - _, spendable_proofs = await wallet3.split_to_send( # type: ignore - wallet3.proofs, 12, set_reserved=True - ) + _, spendable_proofs = await wallet3.split_to_send(wallet3.proofs, 12, set_reserved=True) # type: ignore assert wallet3.available_balance == 64 - 12 await wallet3.redeem(spendable_proofs)