chore: update black, new formatting + pre-commit (#3885)
This commit is contained in:
@@ -14,11 +14,11 @@ repos:
|
|||||||
- id: mixed-line-ending
|
- id: mixed-line-ending
|
||||||
- id: check-case-conflict
|
- id: check-case-conflict
|
||||||
- repo: https://github.com/psf/black
|
- repo: https://github.com/psf/black
|
||||||
rev: 25.1.0
|
rev: 26.3.1
|
||||||
hooks:
|
hooks:
|
||||||
- id: black
|
- id: black
|
||||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||||
rev: v0.12.10
|
rev: v0.14.10
|
||||||
hooks:
|
hooks:
|
||||||
- id: ruff
|
- id: ruff
|
||||||
args: [ --fix, --exit-non-zero-on-fix ]
|
args: [ --fix, --exit-non-zero-on-fix ]
|
||||||
|
|||||||
@@ -149,14 +149,12 @@ async def get_payments_paginated( # noqa: C901
|
|||||||
f"(status = '{PaymentState.SUCCESS}' OR status = '{PaymentState.PENDING}')"
|
f"(status = '{PaymentState.SUCCESS}' OR status = '{PaymentState.PENDING}')"
|
||||||
)
|
)
|
||||||
elif complete:
|
elif complete:
|
||||||
clause.append(
|
clause.append(f"""
|
||||||
f"""
|
|
||||||
(
|
(
|
||||||
status = '{PaymentState.SUCCESS}'
|
status = '{PaymentState.SUCCESS}'
|
||||||
OR (amount < 0 AND status = '{PaymentState.PENDING}')
|
OR (amount < 0 AND status = '{PaymentState.PENDING}')
|
||||||
)
|
)
|
||||||
"""
|
""")
|
||||||
)
|
|
||||||
elif pending:
|
elif pending:
|
||||||
clause.append(f"status = '{PaymentState.PENDING}'")
|
clause.append(f"status = '{PaymentState.PENDING}'")
|
||||||
elif failed:
|
elif failed:
|
||||||
@@ -346,14 +344,12 @@ async def get_payments_history(
|
|||||||
"wallet_id": wallet_id,
|
"wallet_id": wallet_id,
|
||||||
}
|
}
|
||||||
# count outgoing payments if they are still pending
|
# count outgoing payments if they are still pending
|
||||||
where = [
|
where = [f"""
|
||||||
f"""
|
|
||||||
wallet_id = :wallet_id AND (
|
wallet_id = :wallet_id AND (
|
||||||
status = '{PaymentState.SUCCESS}'
|
status = '{PaymentState.SUCCESS}'
|
||||||
OR (amount < 0 AND status = '{PaymentState.PENDING}')
|
OR (amount < 0 AND status = '{PaymentState.PENDING}')
|
||||||
)
|
)
|
||||||
"""
|
"""]
|
||||||
]
|
|
||||||
clause = filters.where(where)
|
clause = filters.where(where)
|
||||||
transactions: list[dict] = await db.fetchall(
|
transactions: list[dict] = await db.fetchall(
|
||||||
# This query is safe from SQL injection:
|
# This query is safe from SQL injection:
|
||||||
|
|||||||
+62
-124
@@ -10,31 +10,26 @@ from lnbits.db import Connection
|
|||||||
|
|
||||||
|
|
||||||
async def m000_create_migrations_table(db: Connection):
|
async def m000_create_migrations_table(db: Connection):
|
||||||
await db.execute(
|
await db.execute("""
|
||||||
"""
|
|
||||||
CREATE TABLE IF NOT EXISTS dbversions (
|
CREATE TABLE IF NOT EXISTS dbversions (
|
||||||
db TEXT PRIMARY KEY,
|
db TEXT PRIMARY KEY,
|
||||||
version INT NOT NULL
|
version INT NOT NULL
|
||||||
)
|
)
|
||||||
"""
|
""")
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def m001_initial(db: Connection):
|
async def m001_initial(db: Connection):
|
||||||
"""
|
"""
|
||||||
Initial LNbits tables.
|
Initial LNbits tables.
|
||||||
"""
|
"""
|
||||||
await db.execute(
|
await db.execute("""
|
||||||
"""
|
|
||||||
CREATE TABLE IF NOT EXISTS accounts (
|
CREATE TABLE IF NOT EXISTS accounts (
|
||||||
id TEXT PRIMARY KEY,
|
id TEXT PRIMARY KEY,
|
||||||
email TEXT,
|
email TEXT,
|
||||||
pass TEXT
|
pass TEXT
|
||||||
);
|
);
|
||||||
"""
|
""")
|
||||||
)
|
await db.execute("""
|
||||||
await db.execute(
|
|
||||||
"""
|
|
||||||
CREATE TABLE IF NOT EXISTS extensions (
|
CREATE TABLE IF NOT EXISTS extensions (
|
||||||
"user" TEXT NOT NULL,
|
"user" TEXT NOT NULL,
|
||||||
extension TEXT NOT NULL,
|
extension TEXT NOT NULL,
|
||||||
@@ -42,10 +37,8 @@ async def m001_initial(db: Connection):
|
|||||||
|
|
||||||
UNIQUE ("user", extension)
|
UNIQUE ("user", extension)
|
||||||
);
|
);
|
||||||
"""
|
""")
|
||||||
)
|
await db.execute("""
|
||||||
await db.execute(
|
|
||||||
"""
|
|
||||||
CREATE TABLE IF NOT EXISTS wallets (
|
CREATE TABLE IF NOT EXISTS wallets (
|
||||||
id TEXT PRIMARY KEY,
|
id TEXT PRIMARY KEY,
|
||||||
name TEXT NOT NULL,
|
name TEXT NOT NULL,
|
||||||
@@ -53,10 +46,8 @@ async def m001_initial(db: Connection):
|
|||||||
adminkey TEXT NOT NULL,
|
adminkey TEXT NOT NULL,
|
||||||
inkey TEXT
|
inkey TEXT
|
||||||
);
|
);
|
||||||
"""
|
""")
|
||||||
)
|
await db.execute(f"""
|
||||||
await db.execute(
|
|
||||||
f"""
|
|
||||||
CREATE TABLE IF NOT EXISTS apipayments (
|
CREATE TABLE IF NOT EXISTS apipayments (
|
||||||
payhash TEXT NOT NULL,
|
payhash TEXT NOT NULL,
|
||||||
amount {db.big_int} NOT NULL,
|
amount {db.big_int} NOT NULL,
|
||||||
@@ -67,11 +58,9 @@ async def m001_initial(db: Connection):
|
|||||||
time TIMESTAMP NOT NULL DEFAULT {db.timestamp_now},
|
time TIMESTAMP NOT NULL DEFAULT {db.timestamp_now},
|
||||||
UNIQUE (wallet, payhash)
|
UNIQUE (wallet, payhash)
|
||||||
);
|
);
|
||||||
"""
|
""")
|
||||||
)
|
|
||||||
|
|
||||||
await db.execute(
|
await db.execute("""
|
||||||
"""
|
|
||||||
CREATE VIEW balances AS
|
CREATE VIEW balances AS
|
||||||
SELECT wallet, COALESCE(SUM(s), 0) AS balance FROM (
|
SELECT wallet, COALESCE(SUM(s), 0) AS balance FROM (
|
||||||
SELECT wallet, SUM(amount) AS s -- incoming
|
SELECT wallet, SUM(amount) AS s -- incoming
|
||||||
@@ -85,8 +74,7 @@ async def m001_initial(db: Connection):
|
|||||||
GROUP BY wallet
|
GROUP BY wallet
|
||||||
)x
|
)x
|
||||||
GROUP BY wallet;
|
GROUP BY wallet;
|
||||||
"""
|
""")
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def m002_add_fields_to_apipayments(db: Connection):
|
async def m002_add_fields_to_apipayments(db: Connection):
|
||||||
@@ -149,8 +137,7 @@ async def m004_ensure_fees_are_always_negative(db: Connection):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
await db.execute("DROP VIEW balances")
|
await db.execute("DROP VIEW balances")
|
||||||
await db.execute(
|
await db.execute("""
|
||||||
"""
|
|
||||||
CREATE VIEW balances AS
|
CREATE VIEW balances AS
|
||||||
SELECT wallet, COALESCE(SUM(s), 0) AS balance FROM (
|
SELECT wallet, COALESCE(SUM(s), 0) AS balance FROM (
|
||||||
SELECT wallet, SUM(amount) AS s -- incoming
|
SELECT wallet, SUM(amount) AS s -- incoming
|
||||||
@@ -164,8 +151,7 @@ async def m004_ensure_fees_are_always_negative(db: Connection):
|
|||||||
GROUP BY wallet
|
GROUP BY wallet
|
||||||
)x
|
)x
|
||||||
GROUP BY wallet;
|
GROUP BY wallet;
|
||||||
"""
|
""")
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def m005_balance_check_balance_notify(db: Connection):
|
async def m005_balance_check_balance_notify(db: Connection):
|
||||||
@@ -174,8 +160,7 @@ async def m005_balance_check_balance_notify(db: Connection):
|
|||||||
LNbits wallet and of balanceNotify URLs supplied by users to empty their wallets.
|
LNbits wallet and of balanceNotify URLs supplied by users to empty their wallets.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
await db.execute(
|
await db.execute("""
|
||||||
"""
|
|
||||||
CREATE TABLE IF NOT EXISTS balance_check (
|
CREATE TABLE IF NOT EXISTS balance_check (
|
||||||
wallet TEXT NOT NULL REFERENCES wallets (id),
|
wallet TEXT NOT NULL REFERENCES wallets (id),
|
||||||
service TEXT NOT NULL,
|
service TEXT NOT NULL,
|
||||||
@@ -183,19 +168,16 @@ async def m005_balance_check_balance_notify(db: Connection):
|
|||||||
|
|
||||||
UNIQUE(wallet, service)
|
UNIQUE(wallet, service)
|
||||||
);
|
);
|
||||||
"""
|
""")
|
||||||
)
|
|
||||||
|
|
||||||
await db.execute(
|
await db.execute("""
|
||||||
"""
|
|
||||||
CREATE TABLE IF NOT EXISTS balance_notify (
|
CREATE TABLE IF NOT EXISTS balance_notify (
|
||||||
wallet TEXT NOT NULL REFERENCES wallets (id),
|
wallet TEXT NOT NULL REFERENCES wallets (id),
|
||||||
url TEXT NOT NULL,
|
url TEXT NOT NULL,
|
||||||
|
|
||||||
UNIQUE(wallet, url)
|
UNIQUE(wallet, url)
|
||||||
);
|
);
|
||||||
"""
|
""")
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def m006_add_invoice_expiry_to_apipayments(db: Connection):
|
async def m006_add_invoice_expiry_to_apipayments(db: Connection):
|
||||||
@@ -262,19 +244,16 @@ async def m007_set_invoice_expiries(db: Connection):
|
|||||||
|
|
||||||
|
|
||||||
async def m008_create_admin_settings_table(db: Connection):
|
async def m008_create_admin_settings_table(db: Connection):
|
||||||
await db.execute(
|
await db.execute("""
|
||||||
"""
|
|
||||||
CREATE TABLE IF NOT EXISTS settings (
|
CREATE TABLE IF NOT EXISTS settings (
|
||||||
super_user TEXT,
|
super_user TEXT,
|
||||||
editable_settings TEXT NOT NULL DEFAULT '{}'
|
editable_settings TEXT NOT NULL DEFAULT '{}'
|
||||||
);
|
);
|
||||||
"""
|
""")
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def m009_create_tinyurl_table(db: Connection):
|
async def m009_create_tinyurl_table(db: Connection):
|
||||||
await db.execute(
|
await db.execute(f"""
|
||||||
f"""
|
|
||||||
CREATE TABLE IF NOT EXISTS tiny_url (
|
CREATE TABLE IF NOT EXISTS tiny_url (
|
||||||
id TEXT PRIMARY KEY,
|
id TEXT PRIMARY KEY,
|
||||||
url TEXT,
|
url TEXT,
|
||||||
@@ -282,13 +261,11 @@ async def m009_create_tinyurl_table(db: Connection):
|
|||||||
wallet TEXT,
|
wallet TEXT,
|
||||||
time TIMESTAMP NOT NULL DEFAULT {db.timestamp_now}
|
time TIMESTAMP NOT NULL DEFAULT {db.timestamp_now}
|
||||||
);
|
);
|
||||||
"""
|
""")
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def m010_create_installed_extensions_table(db: Connection):
|
async def m010_create_installed_extensions_table(db: Connection):
|
||||||
await db.execute(
|
await db.execute("""
|
||||||
"""
|
|
||||||
CREATE TABLE IF NOT EXISTS installed_extensions (
|
CREATE TABLE IF NOT EXISTS installed_extensions (
|
||||||
id TEXT PRIMARY KEY,
|
id TEXT PRIMARY KEY,
|
||||||
version TEXT NOT NULL,
|
version TEXT NOT NULL,
|
||||||
@@ -299,8 +276,7 @@ async def m010_create_installed_extensions_table(db: Connection):
|
|||||||
active BOOLEAN DEFAULT false,
|
active BOOLEAN DEFAULT false,
|
||||||
meta TEXT NOT NULL DEFAULT '{}'
|
meta TEXT NOT NULL DEFAULT '{}'
|
||||||
);
|
);
|
||||||
"""
|
""")
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def m011_optimize_balances_view(db: Connection):
|
async def m011_optimize_balances_view(db: Connection):
|
||||||
@@ -309,23 +285,19 @@ async def m011_optimize_balances_view(db: Connection):
|
|||||||
over the payments table instead of 2.
|
over the payments table instead of 2.
|
||||||
"""
|
"""
|
||||||
await db.execute("DROP VIEW balances")
|
await db.execute("DROP VIEW balances")
|
||||||
await db.execute(
|
await db.execute("""
|
||||||
"""
|
|
||||||
CREATE VIEW balances AS
|
CREATE VIEW balances AS
|
||||||
SELECT wallet, SUM(amount - abs(fee)) AS balance
|
SELECT wallet, SUM(amount - abs(fee)) AS balance
|
||||||
FROM apipayments
|
FROM apipayments
|
||||||
WHERE (pending = false AND amount > 0) OR amount < 0
|
WHERE (pending = false AND amount > 0) OR amount < 0
|
||||||
GROUP BY wallet
|
GROUP BY wallet
|
||||||
"""
|
""")
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def m012_add_currency_to_wallet(db: Connection):
|
async def m012_add_currency_to_wallet(db: Connection):
|
||||||
await db.execute(
|
await db.execute("""
|
||||||
"""
|
|
||||||
ALTER TABLE wallets ADD COLUMN currency TEXT
|
ALTER TABLE wallets ADD COLUMN currency TEXT
|
||||||
"""
|
""")
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def m013_add_deleted_to_wallets(db: Connection):
|
async def m013_add_deleted_to_wallets(db: Connection):
|
||||||
@@ -345,15 +317,13 @@ async def m014_set_deleted_wallets(db: Connection):
|
|||||||
Sets deleted column to wallets.
|
Sets deleted column to wallets.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
result = await db.execute(
|
result = await db.execute("""
|
||||||
"""
|
|
||||||
SELECT *
|
SELECT *
|
||||||
FROM wallets
|
FROM wallets
|
||||||
WHERE user LIKE 'del:%'
|
WHERE user LIKE 'del:%'
|
||||||
AND adminkey LIKE 'del:%'
|
AND adminkey LIKE 'del:%'
|
||||||
AND inkey LIKE 'del:%'
|
AND inkey LIKE 'del:%'
|
||||||
"""
|
""")
|
||||||
)
|
|
||||||
rows = result.mappings().all()
|
rows = result.mappings().all()
|
||||||
|
|
||||||
for row in rows:
|
for row in rows:
|
||||||
@@ -386,8 +356,7 @@ async def m014_set_deleted_wallets(db: Connection):
|
|||||||
|
|
||||||
|
|
||||||
async def m015_create_push_notification_subscriptions_table(db: Connection):
|
async def m015_create_push_notification_subscriptions_table(db: Connection):
|
||||||
await db.execute(
|
await db.execute(f"""
|
||||||
f"""
|
|
||||||
CREATE TABLE IF NOT EXISTS webpush_subscriptions (
|
CREATE TABLE IF NOT EXISTS webpush_subscriptions (
|
||||||
endpoint TEXT NOT NULL,
|
endpoint TEXT NOT NULL,
|
||||||
"user" TEXT NOT NULL,
|
"user" TEXT NOT NULL,
|
||||||
@@ -396,8 +365,7 @@ async def m015_create_push_notification_subscriptions_table(db: Connection):
|
|||||||
timestamp TIMESTAMP NOT NULL DEFAULT {db.timestamp_now},
|
timestamp TIMESTAMP NOT NULL DEFAULT {db.timestamp_now},
|
||||||
PRIMARY KEY (endpoint, "user")
|
PRIMARY KEY (endpoint, "user")
|
||||||
);
|
);
|
||||||
"""
|
""")
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def m016_add_username_column_to_accounts(db: Connection):
|
async def m016_add_username_column_to_accounts(db: Connection):
|
||||||
@@ -484,8 +452,7 @@ async def m018_balances_view_exclude_deleted(db: Connection):
|
|||||||
Make deleted wallets not show up in the balances view.
|
Make deleted wallets not show up in the balances view.
|
||||||
"""
|
"""
|
||||||
await db.execute("DROP VIEW balances")
|
await db.execute("DROP VIEW balances")
|
||||||
await db.execute(
|
await db.execute("""
|
||||||
"""
|
|
||||||
CREATE VIEW balances AS
|
CREATE VIEW balances AS
|
||||||
SELECT apipayments.wallet,
|
SELECT apipayments.wallet,
|
||||||
SUM(apipayments.amount - ABS(apipayments.fee)) AS balance
|
SUM(apipayments.amount - ABS(apipayments.fee)) AS balance
|
||||||
@@ -495,8 +462,7 @@ async def m018_balances_view_exclude_deleted(db: Connection):
|
|||||||
AND ((apipayments.pending = false AND apipayments.amount > 0)
|
AND ((apipayments.pending = false AND apipayments.amount > 0)
|
||||||
OR apipayments.amount < 0)
|
OR apipayments.amount < 0)
|
||||||
GROUP BY wallet
|
GROUP BY wallet
|
||||||
"""
|
""")
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def m019_balances_view_based_on_wallets(db: Connection):
|
async def m019_balances_view_based_on_wallets(db: Connection):
|
||||||
@@ -505,8 +471,7 @@ async def m019_balances_view_based_on_wallets(db: Connection):
|
|||||||
Important for querying whole lnbits balances.
|
Important for querying whole lnbits balances.
|
||||||
"""
|
"""
|
||||||
await db.execute("DROP VIEW balances")
|
await db.execute("DROP VIEW balances")
|
||||||
await db.execute(
|
await db.execute("""
|
||||||
"""
|
|
||||||
CREATE VIEW balances AS
|
CREATE VIEW balances AS
|
||||||
SELECT apipayments.wallet,
|
SELECT apipayments.wallet,
|
||||||
SUM(apipayments.amount - ABS(apipayments.fee)) AS balance
|
SUM(apipayments.amount - ABS(apipayments.fee)) AS balance
|
||||||
@@ -516,8 +481,7 @@ async def m019_balances_view_based_on_wallets(db: Connection):
|
|||||||
AND ((apipayments.pending = false AND apipayments.amount > 0)
|
AND ((apipayments.pending = false AND apipayments.amount > 0)
|
||||||
OR apipayments.amount < 0)
|
OR apipayments.amount < 0)
|
||||||
GROUP BY apipayments.wallet
|
GROUP BY apipayments.wallet
|
||||||
"""
|
""")
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def m020_add_column_column_to_user_extensions(db: Connection):
|
async def m020_add_column_column_to_user_extensions(db: Connection):
|
||||||
@@ -536,8 +500,7 @@ async def m021_add_success_failed_to_apipayments(db: Connection):
|
|||||||
await db.execute("UPDATE apipayments SET status = 'success' WHERE NOT pending")
|
await db.execute("UPDATE apipayments SET status = 'success' WHERE NOT pending")
|
||||||
|
|
||||||
await db.execute("DROP VIEW balances")
|
await db.execute("DROP VIEW balances")
|
||||||
await db.execute(
|
await db.execute("""
|
||||||
"""
|
|
||||||
CREATE VIEW balances AS
|
CREATE VIEW balances AS
|
||||||
SELECT apipayments.wallet,
|
SELECT apipayments.wallet,
|
||||||
SUM(apipayments.amount - ABS(apipayments.fee)) AS balance
|
SUM(apipayments.amount - ABS(apipayments.fee)) AS balance
|
||||||
@@ -549,8 +512,7 @@ async def m021_add_success_failed_to_apipayments(db: Connection):
|
|||||||
OR (apipayments.status IN ('success', 'pending') AND apipayments.amount < 0)
|
OR (apipayments.status IN ('success', 'pending') AND apipayments.amount < 0)
|
||||||
)
|
)
|
||||||
GROUP BY apipayments.wallet
|
GROUP BY apipayments.wallet
|
||||||
"""
|
""")
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def m022_add_pubkey_to_accounts(db: Connection):
|
async def m022_add_pubkey_to_accounts(db: Connection):
|
||||||
@@ -581,8 +543,7 @@ async def m024_drop_pending(db: Connection):
|
|||||||
|
|
||||||
async def m025_refresh_view(db: Connection):
|
async def m025_refresh_view(db: Connection):
|
||||||
await db.execute("DROP VIEW balances")
|
await db.execute("DROP VIEW balances")
|
||||||
await db.execute(
|
await db.execute("""
|
||||||
"""
|
|
||||||
CREATE VIEW balances AS
|
CREATE VIEW balances AS
|
||||||
SELECT apipayments.wallet_id,
|
SELECT apipayments.wallet_id,
|
||||||
SUM(apipayments.amount - ABS(apipayments.fee)) AS balance
|
SUM(apipayments.amount - ABS(apipayments.fee)) AS balance
|
||||||
@@ -594,8 +555,7 @@ async def m025_refresh_view(db: Connection):
|
|||||||
OR (apipayments.status IN ('success', 'pending') AND apipayments.amount < 0)
|
OR (apipayments.status IN ('success', 'pending') AND apipayments.amount < 0)
|
||||||
)
|
)
|
||||||
GROUP BY apipayments.wallet_id
|
GROUP BY apipayments.wallet_id
|
||||||
"""
|
""")
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def m026_update_payment_table(db: Connection):
|
async def m026_update_payment_table(db: Connection):
|
||||||
@@ -658,8 +618,7 @@ async def m027_update_apipayments_data(db: Connection):
|
|||||||
|
|
||||||
async def m028_update_settings(db: Connection):
|
async def m028_update_settings(db: Connection):
|
||||||
|
|
||||||
await db.execute(
|
await db.execute("""
|
||||||
"""
|
|
||||||
CREATE TABLE IF NOT EXISTS system_settings (
|
CREATE TABLE IF NOT EXISTS system_settings (
|
||||||
id TEXT PRIMARY KEY,
|
id TEXT PRIMARY KEY,
|
||||||
value TEXT,
|
value TEXT,
|
||||||
@@ -667,8 +626,7 @@ async def m028_update_settings(db: Connection):
|
|||||||
|
|
||||||
UNIQUE (id, tag)
|
UNIQUE (id, tag)
|
||||||
);
|
);
|
||||||
"""
|
""")
|
||||||
)
|
|
||||||
|
|
||||||
async def _insert_key_value(id_: str, value: Any):
|
async def _insert_key_value(id_: str, value: Any):
|
||||||
await db.execute(
|
await db.execute(
|
||||||
@@ -691,8 +649,7 @@ async def m028_update_settings(db: Connection):
|
|||||||
|
|
||||||
|
|
||||||
async def m029_create_audit_table(db: Connection):
|
async def m029_create_audit_table(db: Connection):
|
||||||
await db.execute(
|
await db.execute(f"""
|
||||||
f"""
|
|
||||||
CREATE TABLE IF NOT EXISTS audit (
|
CREATE TABLE IF NOT EXISTS audit (
|
||||||
component TEXT,
|
component TEXT,
|
||||||
ip_address TEXT,
|
ip_address TEXT,
|
||||||
@@ -706,16 +663,13 @@ async def m029_create_audit_table(db: Connection):
|
|||||||
delete_at TIMESTAMP,
|
delete_at TIMESTAMP,
|
||||||
created_at TIMESTAMP NOT NULL DEFAULT {db.timestamp_now}
|
created_at TIMESTAMP NOT NULL DEFAULT {db.timestamp_now}
|
||||||
);
|
);
|
||||||
"""
|
""")
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def m030_add_user_api_tokens_column(db: Connection):
|
async def m030_add_user_api_tokens_column(db: Connection):
|
||||||
await db.execute(
|
await db.execute("""
|
||||||
"""
|
|
||||||
ALTER TABLE accounts ADD COLUMN access_control_list TEXT
|
ALTER TABLE accounts ADD COLUMN access_control_list TEXT
|
||||||
"""
|
""")
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def m031_add_color_and_icon_to_wallets(db: Connection):
|
async def m031_add_color_and_icon_to_wallets(db: Connection):
|
||||||
@@ -738,32 +692,25 @@ async def m033_update_payment_table(db: Connection):
|
|||||||
|
|
||||||
|
|
||||||
async def m034_add_stored_paylinks_to_wallet(db: Connection):
|
async def m034_add_stored_paylinks_to_wallet(db: Connection):
|
||||||
await db.execute(
|
await db.execute("""
|
||||||
"""
|
|
||||||
ALTER TABLE wallets ADD COLUMN stored_paylinks TEXT
|
ALTER TABLE wallets ADD COLUMN stored_paylinks TEXT
|
||||||
"""
|
""")
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def m035_add_wallet_type_column(db: Connection):
|
async def m035_add_wallet_type_column(db: Connection):
|
||||||
await db.execute(
|
await db.execute("""
|
||||||
"""
|
|
||||||
ALTER TABLE wallets ADD COLUMN wallet_type TEXT DEFAULT 'lightning'
|
ALTER TABLE wallets ADD COLUMN wallet_type TEXT DEFAULT 'lightning'
|
||||||
"""
|
""")
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def m036_add_shared_wallet_column(db: Connection):
|
async def m036_add_shared_wallet_column(db: Connection):
|
||||||
await db.execute(
|
await db.execute("""
|
||||||
"""
|
|
||||||
ALTER TABLE wallets ADD COLUMN shared_wallet_id TEXT
|
ALTER TABLE wallets ADD COLUMN shared_wallet_id TEXT
|
||||||
"""
|
""")
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def m037_create_assets_table(db: Connection):
|
async def m037_create_assets_table(db: Connection):
|
||||||
await db.execute(
|
await db.execute(f"""
|
||||||
f"""
|
|
||||||
CREATE TABLE IF NOT EXISTS assets (
|
CREATE TABLE IF NOT EXISTS assets (
|
||||||
id TEXT PRIMARY KEY,
|
id TEXT PRIMARY KEY,
|
||||||
user_id TEXT NOT NULL,
|
user_id TEXT NOT NULL,
|
||||||
@@ -776,16 +723,13 @@ async def m037_create_assets_table(db: Connection):
|
|||||||
data {db.blob} NOT NULL,
|
data {db.blob} NOT NULL,
|
||||||
created_at TIMESTAMP NOT NULL DEFAULT {db.timestamp_now}
|
created_at TIMESTAMP NOT NULL DEFAULT {db.timestamp_now}
|
||||||
);
|
);
|
||||||
"""
|
""")
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def m038_add_labels_for_payments(db: Connection):
|
async def m038_add_labels_for_payments(db: Connection):
|
||||||
await db.execute(
|
await db.execute("""
|
||||||
"""
|
|
||||||
ALTER TABLE apipayments ADD COLUMN labels TEXT
|
ALTER TABLE apipayments ADD COLUMN labels TEXT
|
||||||
"""
|
""")
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def m039_index_payments(db: Connection):
|
async def m039_index_payments(db: Connection):
|
||||||
@@ -804,11 +748,9 @@ async def m039_index_payments(db: Connection):
|
|||||||
]
|
]
|
||||||
for index in indexes:
|
for index in indexes:
|
||||||
logger.debug(f"Creating index idx_payments_{index}...")
|
logger.debug(f"Creating index idx_payments_{index}...")
|
||||||
await db.execute(
|
await db.execute(f"""
|
||||||
f"""
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_payments_{index} ON apipayments ({index});
|
CREATE INDEX IF NOT EXISTS idx_payments_{index} ON apipayments ({index});
|
||||||
"""
|
""")
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def m040_index_wallets(db: Connection):
|
async def m040_index_wallets(db: Connection):
|
||||||
@@ -825,11 +767,9 @@ async def m040_index_wallets(db: Connection):
|
|||||||
|
|
||||||
for index in indexes:
|
for index in indexes:
|
||||||
logger.debug(f"Creating index idx_wallets_{index}...")
|
logger.debug(f"Creating index idx_wallets_{index}...")
|
||||||
await db.execute(
|
await db.execute(f"""
|
||||||
f"""
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_wallets_{index} ON wallets ("{index}");
|
CREATE INDEX IF NOT EXISTS idx_wallets_{index} ON wallets ("{index}");
|
||||||
"""
|
""")
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def m042_index_accounts(db: Connection):
|
async def m042_index_accounts(db: Connection):
|
||||||
@@ -843,11 +783,9 @@ async def m042_index_accounts(db: Connection):
|
|||||||
|
|
||||||
for index in indexes:
|
for index in indexes:
|
||||||
logger.debug(f"Creating index idx_wallets_{index}...")
|
logger.debug(f"Creating index idx_wallets_{index}...")
|
||||||
await db.execute(
|
await db.execute(f"""
|
||||||
f"""
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_accounts_{index} ON accounts ("{index}");
|
CREATE INDEX IF NOT EXISTS idx_accounts_{index} ON accounts ("{index}");
|
||||||
"""
|
""")
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def m043_add_ui_customization_to_accounts(db: Connection):
|
async def m043_add_ui_customization_to_accounts(db: Connection):
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ def decrypt_content(
|
|||||||
1:
|
1:
|
||||||
]
|
]
|
||||||
# extract iv and content
|
# extract iv and content
|
||||||
(encrypted_content_b64, iv_b64) = content.split("?iv=")
|
encrypted_content_b64, iv_b64 = content.split("?iv=")
|
||||||
encrypted_content = base64.b64decode(encrypted_content_b64.encode("ascii"))
|
encrypted_content = base64.b64decode(encrypted_content_b64.encode("ascii"))
|
||||||
iv = base64.b64decode(iv_b64.encode("ascii"))
|
iv = base64.b64decode(iv_b64.encode("ascii"))
|
||||||
# Decrypt
|
# Decrypt
|
||||||
|
|||||||
+1
-1
@@ -64,7 +64,7 @@ migration = ["psycopg2-binary==2.9.11"]
|
|||||||
|
|
||||||
[dependency-groups]
|
[dependency-groups]
|
||||||
dev = [
|
dev = [
|
||||||
"black>=25.12.0,<26.0.0",
|
"black~=26.3.1",
|
||||||
"mypy==1.17.1",
|
"mypy==1.17.1",
|
||||||
"types-protobuf>=6.32.1.20251210,<7.0.0",
|
"types-protobuf>=6.32.1.20251210,<7.0.0",
|
||||||
"pre-commit>=4.5.1,<5.0.0",
|
"pre-commit>=4.5.1,<5.0.0",
|
||||||
|
|||||||
@@ -6,25 +6,21 @@ from tests.helpers import DbTestModel
|
|||||||
@pytest.fixture(scope="session")
|
@pytest.fixture(scope="session")
|
||||||
async def fetch_page(db):
|
async def fetch_page(db):
|
||||||
await db.execute("DROP TABLE IF EXISTS test_db_fetch_page")
|
await db.execute("DROP TABLE IF EXISTS test_db_fetch_page")
|
||||||
await db.execute(
|
await db.execute("""
|
||||||
"""
|
|
||||||
CREATE TABLE test_db_fetch_page (
|
CREATE TABLE test_db_fetch_page (
|
||||||
id TEXT PRIMARY KEY,
|
id TEXT PRIMARY KEY,
|
||||||
value TEXT NOT NULL,
|
value TEXT NOT NULL,
|
||||||
name TEXT NOT NULL
|
name TEXT NOT NULL
|
||||||
)
|
)
|
||||||
"""
|
""")
|
||||||
)
|
await db.execute("""
|
||||||
await db.execute(
|
|
||||||
"""
|
|
||||||
INSERT INTO test_db_fetch_page (id, name, value) VALUES
|
INSERT INTO test_db_fetch_page (id, name, value) VALUES
|
||||||
('1', 'Alice', 'foo'),
|
('1', 'Alice', 'foo'),
|
||||||
('2', 'Bob', 'bar'),
|
('2', 'Bob', 'bar'),
|
||||||
('3', 'Carol', 'bar'),
|
('3', 'Carol', 'bar'),
|
||||||
('4', 'Dave', 'bar'),
|
('4', 'Dave', 'bar'),
|
||||||
('5', 'Dave', 'foo')
|
('5', 'Dave', 'foo')
|
||||||
"""
|
""")
|
||||||
)
|
|
||||||
yield
|
yield
|
||||||
await db.execute("DROP TABLE test_db_fetch_page")
|
await db.execute("DROP TABLE test_db_fetch_page")
|
||||||
|
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ def encrypt_content(priv_key, dest_pub_key, content):
|
|||||||
def decrypt_content(priv_key, source_pub_key, content):
|
def decrypt_content(priv_key, source_pub_key, content):
|
||||||
p = PublicKey(bytes.fromhex("02" + source_pub_key))
|
p = PublicKey(bytes.fromhex("02" + source_pub_key))
|
||||||
shared = p.multiply(bytes.fromhex(priv_key)).format()[1:]
|
shared = p.multiply(bytes.fromhex(priv_key)).format()[1:]
|
||||||
(encrypted_content_b64, iv_b64) = content.split("?iv=")
|
encrypted_content_b64, iv_b64 = content.split("?iv=")
|
||||||
encrypted_content = base64.b64decode(encrypted_content_b64.encode("ascii"))
|
encrypted_content = base64.b64decode(encrypted_content_b64.encode("ascii"))
|
||||||
iv = base64.b64decode(iv_b64.encode("ascii"))
|
iv = base64.b64decode(iv_b64.encode("ascii"))
|
||||||
aes = AES.new(shared, AES.MODE_CBC, iv)
|
aes = AES.new(shared, AES.MODE_CBC, iv)
|
||||||
|
|||||||
+4
-8
@@ -136,12 +136,10 @@ def migrate_db(file: str, schema: str, exclude_tables: list[str] | None = None):
|
|||||||
assert os.path.isfile(file), f"{file} does not exist!"
|
assert os.path.isfile(file), f"{file} does not exist!"
|
||||||
|
|
||||||
sqlite_cursor = get_sqlite_cursor(file)
|
sqlite_cursor = get_sqlite_cursor(file)
|
||||||
tables = sqlite_cursor.execute(
|
tables = sqlite_cursor.execute("""
|
||||||
"""
|
|
||||||
SELECT name FROM sqlite_master
|
SELECT name FROM sqlite_master
|
||||||
WHERE type='table' AND name not like 'sqlite?_%' escape '?'
|
WHERE type='table' AND name not like 'sqlite?_%' escape '?'
|
||||||
"""
|
""").fetchall()
|
||||||
).fetchall()
|
|
||||||
|
|
||||||
for table in tables:
|
for table in tables:
|
||||||
table_name = table[0]
|
table_name = table[0]
|
||||||
@@ -184,11 +182,9 @@ def build_table_columns(file: str, schema: str, table_name: str):
|
|||||||
sqlite_columns = sqlite_cursor.execute(
|
sqlite_columns = sqlite_cursor.execute(
|
||||||
f"PRAGMA table_info({table_name})"
|
f"PRAGMA table_info({table_name})"
|
||||||
).fetchall()
|
).fetchall()
|
||||||
pg_cursor.execute(
|
pg_cursor.execute(f"""
|
||||||
f"""
|
|
||||||
SELECT table_name, column_name, udt_name FROM information_schema.columns
|
SELECT table_name, column_name, udt_name FROM information_schema.columns
|
||||||
WHERE table_schema = '{schema}'AND table_name = '{table_name}';"""
|
WHERE table_schema = '{schema}'AND table_name = '{table_name}';""")
|
||||||
)
|
|
||||||
pg_columns = pg_cursor.fetchall()
|
pg_columns = pg_cursor.fetchall()
|
||||||
|
|
||||||
columns = []
|
columns = []
|
||||||
|
|||||||
@@ -332,7 +332,7 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "black"
|
name = "black"
|
||||||
version = "25.12.0"
|
version = "26.3.1"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "click" },
|
{ name = "click" },
|
||||||
@@ -344,24 +344,24 @@ dependencies = [
|
|||||||
{ name = "tomli", marker = "python_full_version < '3.11'" },
|
{ name = "tomli", marker = "python_full_version < '3.11'" },
|
||||||
{ name = "typing-extensions", marker = "python_full_version < '3.11'" },
|
{ name = "typing-extensions", marker = "python_full_version < '3.11'" },
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/c4/d9/07b458a3f1c525ac392b5edc6b191ff140b596f9d77092429417a54e249d/black-25.12.0.tar.gz", hash = "sha256:8d3dd9cea14bff7ddc0eb243c811cdb1a011ebb4800a5f0335a01a68654796a7", size = 659264, upload-time = "2025-12-08T01:40:52.501Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/e1/c5/61175d618685d42b005847464b8fb4743a67b1b8fdb75e50e5a96c31a27a/black-26.3.1.tar.gz", hash = "sha256:2c50f5063a9641c7eed7795014ba37b0f5fa227f3d408b968936e24bc0566b07", size = 666155, upload-time = "2026-03-12T03:36:03.593Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/37/d5/8d3145999d380e5d09bb00b0f7024bf0a8ccb5c07b5648e9295f02ec1d98/black-25.12.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f85ba1ad15d446756b4ab5f3044731bf68b777f8f9ac9cdabd2425b97cd9c4e8", size = 1895720, upload-time = "2025-12-08T01:46:58.197Z" },
|
{ url = "https://files.pythonhosted.org/packages/32/a8/11170031095655d36ebc6664fe0897866f6023892396900eec0e8fdc4299/black-26.3.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:86a8b5035fce64f5dcd1b794cf8ec4d31fe458cf6ce3986a30deb434df82a1d2", size = 1866562, upload-time = "2026-03-12T03:39:58.639Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/06/97/7acc85c4add41098f4f076b21e3e4e383ad6ed0a3da26b2c89627241fc11/black-25.12.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:546eecfe9a3a6b46f9d69d8a642585a6eaf348bcbbc4d87a19635570e02d9f4a", size = 1727193, upload-time = "2025-12-08T01:52:26.674Z" },
|
{ url = "https://files.pythonhosted.org/packages/69/ce/9e7548d719c3248c6c2abfd555d11169457cbd584d98d179111338423790/black-26.3.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5602bdb96d52d2d0672f24f6ffe5218795736dd34807fd0fd55ccd6bf206168b", size = 1703623, upload-time = "2026-03-12T03:40:00.347Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/24/f0/fdf0eb8ba907ddeb62255227d29d349e8256ef03558fbcadfbc26ecfe3b2/black-25.12.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:17dcc893da8d73d8f74a596f64b7c98ef5239c2cd2b053c0f25912c4494bf9ea", size = 1774506, upload-time = "2025-12-08T01:46:25.721Z" },
|
{ url = "https://files.pythonhosted.org/packages/7f/0a/8d17d1a9c06f88d3d030d0b1d4373c1551146e252afe4547ed601c0e697f/black-26.3.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6c54a4a82e291a1fee5137371ab488866b7c86a3305af4026bdd4dc78642e1ac", size = 1768388, upload-time = "2026-03-12T03:40:01.765Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/e4/f5/9203a78efe00d13336786b133c6180a9303d46908a9aa72d1104ca214222/black-25.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:09524b0e6af8ba7a3ffabdfc7a9922fb9adef60fed008c7cd2fc01f3048e6e6f", size = 1416085, upload-time = "2025-12-08T01:46:06.073Z" },
|
{ url = "https://files.pythonhosted.org/packages/52/79/c1ee726e221c863cde5164f925bacf183dfdf0397d4e3f94889439b947b4/black-26.3.1-cp310-cp310-win_amd64.whl", hash = "sha256:6e131579c243c98f35bce64a7e08e87fb2d610544754675d4a0e73a070a5aa3a", size = 1412969, upload-time = "2026-03-12T03:40:03.252Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/ba/cc/7a6090e6b081c3316282c05c546e76affdce7bf7a3b7d2c3a2a69438bd01/black-25.12.0-cp310-cp310-win_arm64.whl", hash = "sha256:b162653ed89eb942758efeb29d5e333ca5bb90e5130216f8369857db5955a7da", size = 1226038, upload-time = "2025-12-08T01:45:29.388Z" },
|
{ url = "https://files.pythonhosted.org/packages/73/a5/15c01d613f5756f68ed8f6d4ec0a1e24b82b18889fa71affd3d1f7fad058/black-26.3.1-cp310-cp310-win_arm64.whl", hash = "sha256:5ed0ca58586c8d9a487352a96b15272b7fa55d139fc8496b519e78023a8dab0a", size = 1220345, upload-time = "2026-03-12T03:40:04.892Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/60/ad/7ac0d0e1e0612788dbc48e62aef8a8e8feffac7eb3d787db4e43b8462fa8/black-25.12.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d0cfa263e85caea2cff57d8f917f9f51adae8e20b610e2b23de35b5b11ce691a", size = 1877003, upload-time = "2025-12-08T01:43:29.967Z" },
|
{ url = "https://files.pythonhosted.org/packages/17/57/5f11c92861f9c92eb9dddf515530bc2d06db843e44bdcf1c83c1427824bc/black-26.3.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:28ef38aee69e4b12fda8dba75e21f9b4f979b490c8ac0baa7cb505369ac9e1ff", size = 1851987, upload-time = "2026-03-12T03:40:06.248Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/e8/dd/a237e9f565f3617a88b49284b59cbca2a4f56ebe68676c1aad0ce36a54a7/black-25.12.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1a2f578ae20c19c50a382286ba78bfbeafdf788579b053d8e4980afb079ab9be", size = 1712639, upload-time = "2025-12-08T01:52:46.756Z" },
|
{ url = "https://files.pythonhosted.org/packages/54/aa/340a1463660bf6831f9e39646bf774086dbd8ca7fc3cded9d59bbdf4ad0a/black-26.3.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bf9bf162ed91a26f1adba8efda0b573bc6924ec1408a52cc6f82cb73ec2b142c", size = 1689499, upload-time = "2026-03-12T03:40:07.642Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/12/80/e187079df1ea4c12a0c63282ddd8b81d5107db6d642f7d7b75a6bcd6fc21/black-25.12.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d3e1b65634b0e471d07ff86ec338819e2ef860689859ef4501ab7ac290431f9b", size = 1758143, upload-time = "2025-12-08T01:45:29.137Z" },
|
{ url = "https://files.pythonhosted.org/packages/f3/01/b726c93d717d72733da031d2de10b92c9fa4c8d0c67e8a8a372076579279/black-26.3.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:474c27574d6d7037c1bc875a81d9be0a9a4f9ee95e62800dab3cfaadbf75acd5", size = 1754369, upload-time = "2026-03-12T03:40:09.279Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/93/b5/3096ccee4f29dc2c3aac57274326c4d2d929a77e629f695f544e159bfae4/black-25.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:a3fa71e3b8dd9f7c6ac4d818345237dfb4175ed3bf37cd5a581dbc4c034f1ec5", size = 1420698, upload-time = "2025-12-08T01:45:53.379Z" },
|
{ url = "https://files.pythonhosted.org/packages/e3/09/61e91881ca291f150cfc9eb7ba19473c2e59df28859a11a88248b5cbbc4d/black-26.3.1-cp311-cp311-win_amd64.whl", hash = "sha256:5e9d0d86df21f2e1677cc4bd090cd0e446278bcbbe49bf3659c308c3e402843e", size = 1413613, upload-time = "2026-03-12T03:40:10.943Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/7e/39/f81c0ffbc25ffbe61c7d0385bf277e62ffc3e52f5ee668d7369d9854fadf/black-25.12.0-cp311-cp311-win_arm64.whl", hash = "sha256:51e267458f7e650afed8445dc7edb3187143003d52a1b710c7321aef22aa9655", size = 1229317, upload-time = "2025-12-08T01:46:35.606Z" },
|
{ url = "https://files.pythonhosted.org/packages/16/73/544f23891b22e7efe4d8f812371ab85b57f6a01b2fc45e3ba2e52ba985b8/black-26.3.1-cp311-cp311-win_arm64.whl", hash = "sha256:9a5e9f45e5d5e1c5b5c29b3bd4265dcc90e8b92cf4534520896ed77f791f4da5", size = 1219719, upload-time = "2026-03-12T03:40:12.597Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/d1/bd/26083f805115db17fda9877b3c7321d08c647df39d0df4c4ca8f8450593e/black-25.12.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:31f96b7c98c1ddaeb07dc0f56c652e25bdedaac76d5b68a059d998b57c55594a", size = 1924178, upload-time = "2025-12-08T01:49:51.048Z" },
|
{ url = "https://files.pythonhosted.org/packages/dc/f8/da5eae4fc75e78e6dceb60624e1b9662ab00d6b452996046dfa9b8a6025b/black-26.3.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b5e6f89631eb88a7302d416594a32faeee9fb8fb848290da9d0a5f2903519fc1", size = 1895920, upload-time = "2026-03-12T03:40:13.921Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/89/6b/ea00d6651561e2bdd9231c4177f4f2ae19cc13a0b0574f47602a7519b6ca/black-25.12.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:05dd459a19e218078a1f98178c13f861fe6a9a5f88fc969ca4d9b49eb1809783", size = 1742643, upload-time = "2025-12-08T01:49:59.09Z" },
|
{ url = "https://files.pythonhosted.org/packages/2c/9f/04e6f26534da2e1629b2b48255c264cabf5eedc5141d04516d9d68a24111/black-26.3.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:41cd2012d35b47d589cb8a16faf8a32ef7a336f56356babd9fcf70939ad1897f", size = 1718499, upload-time = "2026-03-12T03:40:15.239Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/6d/f3/360fa4182e36e9875fabcf3a9717db9d27a8d11870f21cff97725c54f35b/black-25.12.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c1f68c5eff61f226934be6b5b80296cf6939e5d2f0c2f7d543ea08b204bfaf59", size = 1800158, upload-time = "2025-12-08T01:44:27.301Z" },
|
{ url = "https://files.pythonhosted.org/packages/04/91/a5935b2a63e31b331060c4a9fdb5a6c725840858c599032a6f3aac94055f/black-26.3.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0f76ff19ec5297dd8e66eb64deda23631e642c9393ab592826fd4bdc97a4bce7", size = 1794994, upload-time = "2026-03-12T03:40:17.124Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/f8/08/2c64830cb6616278067e040acca21d4f79727b23077633953081c9445d61/black-25.12.0-cp312-cp312-win_amd64.whl", hash = "sha256:274f940c147ddab4442d316b27f9e332ca586d39c85ecf59ebdea82cc9ee8892", size = 1426197, upload-time = "2025-12-08T01:45:51.198Z" },
|
{ url = "https://files.pythonhosted.org/packages/e7/0a/86e462cdd311a3c2a8ece708d22aba17d0b2a0d5348ca34b40cdcbea512e/black-26.3.1-cp312-cp312-win_amd64.whl", hash = "sha256:ddb113db38838eb9f043623ba274cfaf7d51d5b0c22ecb30afe58b1bb8322983", size = 1420867, upload-time = "2026-03-12T03:40:18.83Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/d4/60/a93f55fd9b9816b7432cf6842f0e3000fdd5b7869492a04b9011a133ee37/black-25.12.0-cp312-cp312-win_arm64.whl", hash = "sha256:169506ba91ef21e2e0591563deda7f00030cb466e747c4b09cb0a9dae5db2f43", size = 1237266, upload-time = "2025-12-08T01:45:10.556Z" },
|
{ url = "https://files.pythonhosted.org/packages/5b/e5/22515a19cb7eaee3440325a6b0d95d2c0e88dd180cb011b12ae488e031d1/black-26.3.1-cp312-cp312-win_arm64.whl", hash = "sha256:dfdd51fc3e64ea4f35873d1b3fb25326773d55d2329ff8449139ebaad7357efb", size = 1230124, upload-time = "2026-03-12T03:40:20.425Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/68/11/21331aed19145a952ad28fca2756a1433ee9308079bd03bd898e903a2e53/black-25.12.0-py3-none-any.whl", hash = "sha256:48ceb36c16dbc84062740049eef990bb2ce07598272e673c17d1a7720c71c828", size = 206191, upload-time = "2025-12-08T01:40:50.963Z" },
|
{ url = "https://files.pythonhosted.org/packages/8e/0d/52d98722666d6fc6c3dd4c76df339501d6efd40e0ff95e6186a7b7f0befd/black-26.3.1-py3-none-any.whl", hash = "sha256:2bd5aa94fc267d38bb21a70d7410a89f1a1d318841855f698746f8e7f51acd1b", size = 207542, upload-time = "2026-03-12T03:36:01.668Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1384,7 +1384,7 @@ provides-extras = ["breez", "liquid", "migration"]
|
|||||||
dev = [
|
dev = [
|
||||||
{ name = "anyio", specifier = ">=4.12.1" },
|
{ name = "anyio", specifier = ">=4.12.1" },
|
||||||
{ name = "asgi-lifespan", specifier = ">=2.1.0,<3.0.0" },
|
{ name = "asgi-lifespan", specifier = ">=2.1.0,<3.0.0" },
|
||||||
{ name = "black", specifier = ">=25.12.0,<26.0.0" },
|
{ name = "black", specifier = "~=26.3.1" },
|
||||||
{ name = "grpcio-tools", specifier = ">=1.76.0,<2.0.0" },
|
{ name = "grpcio-tools", specifier = ">=1.76.0,<2.0.0" },
|
||||||
{ name = "json5", specifier = ">=0.13.0,<1.0.0" },
|
{ name = "json5", specifier = ">=0.13.0,<1.0.0" },
|
||||||
{ name = "mock", specifier = ">=5.2.0,<6.0.0" },
|
{ name = "mock", specifier = ">=5.2.0,<6.0.0" },
|
||||||
@@ -1716,11 +1716,11 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pathspec"
|
name = "pathspec"
|
||||||
version = "0.12.1"
|
version = "1.0.4"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/ca/bc/f35b8446f4531a7cb215605d100cd88b7ac6f44ab3fc94870c120ab3adbf/pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712", size = 51043, upload-time = "2023-12-10T22:30:45Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/fa/36/e27608899f9b8d4dff0617b2d9ab17ca5608956ca44461ac14ac48b44015/pathspec-1.0.4.tar.gz", hash = "sha256:0210e2ae8a21a9137c0d470578cb0e595af87edaa6ebf12ff176f14a02e0e645", size = 131200, upload-time = "2026-01-27T03:59:46.938Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191, upload-time = "2023-12-10T22:30:43.14Z" },
|
{ url = "https://files.pythonhosted.org/packages/ef/3c/2c197d226f9ea224a9ab8d197933f9da0ae0aac5b6e0f884e2b8d9c8e9f7/pathspec-1.0.4-py3-none-any.whl", hash = "sha256:fb6ae2fd4e7c921a165808a552060e722767cfa526f99ca5156ed2ce45a5c723", size = 55206, upload-time = "2026-01-27T03:59:45.137Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2190,11 +2190,26 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pytokens"
|
name = "pytokens"
|
||||||
version = "0.3.0"
|
version = "0.4.1"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/4e/8d/a762be14dae1c3bf280202ba3172020b2b0b4c537f94427435f19c413b72/pytokens-0.3.0.tar.gz", hash = "sha256:2f932b14ed08de5fcf0b391ace2642f858f1394c0857202959000b68ed7a458a", size = 17644, upload-time = "2025-11-05T13:36:35.34Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/b6/34/b4e015b99031667a7b960f888889c5bd34ef585c85e1cb56a594b92836ac/pytokens-0.4.1.tar.gz", hash = "sha256:292052fe80923aae2260c073f822ceba21f3872ced9a68bb7953b348e561179a", size = 23015, upload-time = "2026-01-30T01:03:45.924Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/84/25/d9db8be44e205a124f6c98bc0324b2bb149b7431c53877fc6d1038dddaf5/pytokens-0.3.0-py3-none-any.whl", hash = "sha256:95b2b5eaf832e469d141a378872480ede3f251a5a5041b8ec6e581d3ac71bbf3", size = 12195, upload-time = "2025-11-05T13:36:33.183Z" },
|
{ url = "https://files.pythonhosted.org/packages/42/24/f206113e05cb8ef51b3850e7ef88f20da6f4bf932190ceb48bd3da103e10/pytokens-0.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2a44ed93ea23415c54f3face3b65ef2b844d96aeb3455b8a69b3df6beab6acc5", size = 161522, upload-time = "2026-01-30T01:02:50.393Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d4/e9/06a6bf1b90c2ed81a9c7d2544232fe5d2891d1cd480e8a1809ca354a8eb2/pytokens-0.4.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:add8bf86b71a5d9fb5b89f023a80b791e04fba57960aa790cc6125f7f1d39dfe", size = 246945, upload-time = "2026-01-30T01:02:52.399Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/69/66/f6fb1007a4c3d8b682d5d65b7c1fb33257587a5f782647091e3408abe0b8/pytokens-0.4.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:670d286910b531c7b7e3c0b453fd8156f250adb140146d234a82219459b9640c", size = 259525, upload-time = "2026-01-30T01:02:53.737Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/04/92/086f89b4d622a18418bac74ab5db7f68cf0c21cf7cc92de6c7b919d76c88/pytokens-0.4.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:4e691d7f5186bd2842c14813f79f8884bb03f5995f0575272009982c5ac6c0f7", size = 262693, upload-time = "2026-01-30T01:02:54.871Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b4/7b/8b31c347cf94a3f900bdde750b2e9131575a61fdb620d3d3c75832262137/pytokens-0.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:27b83ad28825978742beef057bfe406ad6ed524b2d28c252c5de7b4a6dd48fa2", size = 103567, upload-time = "2026-01-30T01:02:56.414Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/3d/92/790ebe03f07b57e53b10884c329b9a1a308648fc083a6d4a39a10a28c8fc/pytokens-0.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d70e77c55ae8380c91c0c18dea05951482e263982911fc7410b1ffd1dadd3440", size = 160864, upload-time = "2026-01-30T01:02:57.882Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/13/25/a4f555281d975bfdd1eba731450e2fe3a95870274da73fb12c40aeae7625/pytokens-0.4.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4a58d057208cb9075c144950d789511220b07636dd2e4708d5645d24de666bdc", size = 248565, upload-time = "2026-01-30T01:02:59.912Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/17/50/bc0394b4ad5b1601be22fa43652173d47e4c9efbf0044c62e9a59b747c56/pytokens-0.4.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b49750419d300e2b5a3813cf229d4e5a4c728dae470bcc89867a9ad6f25a722d", size = 260824, upload-time = "2026-01-30T01:03:01.471Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/4e/54/3e04f9d92a4be4fc6c80016bc396b923d2a6933ae94b5f557c939c460ee0/pytokens-0.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d9907d61f15bf7261d7e775bd5d7ee4d2930e04424bab1972591918497623a16", size = 264075, upload-time = "2026-01-30T01:03:04.143Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d1/1b/44b0326cb5470a4375f37988aea5d61b5cc52407143303015ebee94abfd6/pytokens-0.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:ee44d0f85b803321710f9239f335aafe16553b39106384cef8e6de40cb4ef2f6", size = 103323, upload-time = "2026-01-30T01:03:05.412Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/41/5d/e44573011401fb82e9d51e97f1290ceb377800fb4eed650b96f4753b499c/pytokens-0.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:140709331e846b728475786df8aeb27d24f48cbcf7bcd449f8de75cae7a45083", size = 160663, upload-time = "2026-01-30T01:03:06.473Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f0/e6/5bbc3019f8e6f21d09c41f8b8654536117e5e211a85d89212d59cbdab381/pytokens-0.4.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6d6c4268598f762bc8e91f5dbf2ab2f61f7b95bdc07953b602db879b3c8c18e1", size = 255626, upload-time = "2026-01-30T01:03:08.177Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/bf/3c/2d5297d82286f6f3d92770289fd439956b201c0a4fc7e72efb9b2293758e/pytokens-0.4.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:24afde1f53d95348b5a0eb19488661147285ca4dd7ed752bbc3e1c6242a304d1", size = 269779, upload-time = "2026-01-30T01:03:09.756Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/20/01/7436e9ad693cebda0551203e0bf28f7669976c60ad07d6402098208476de/pytokens-0.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5ad948d085ed6c16413eb5fec6b3e02fa00dc29a2534f088d3302c47eb59adf9", size = 268076, upload-time = "2026-01-30T01:03:10.957Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/2e/df/533c82a3c752ba13ae7ef238b7f8cdd272cf1475f03c63ac6cf3fcfb00b6/pytokens-0.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:3f901fe783e06e48e8cbdc82d631fca8f118333798193e026a50ce1b3757ea68", size = 103552, upload-time = "2026-01-30T01:03:12.066Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/c6/78/397db326746f0a342855b81216ae1f0a32965deccfd7c830a2dbc66d2483/pytokens-0.4.1-py3-none-any.whl", hash = "sha256:26cef14744a8385f35d0e095dc8b3a7583f6c953c2e3d269c7f82484bf5ad2de", size = 13729, upload-time = "2026-01-30T01:03:45.029Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|||||||
Reference in New Issue
Block a user