command fixes

This commit is contained in:
Lex Berezhny 2020-10-17 09:33:44 -04:00
parent cc2837c021
commit 1a4a2db1b1
9 changed files with 85 additions and 68 deletions

View file

@ -262,7 +262,11 @@ def main(argv=None):
if args.help: if args.help:
print(doc) print(doc)
else: else:
parsed = docopt(doc, command_args) parsed = docopt(
# TODO: ugly hack because docopt doesn't support commands with spaces in them
doc.replace(api_method_name.replace('_', ' '), api_method_name, 1),
command_args
)
params = set_kwargs(parsed) params = set_kwargs(parsed)
asyncio.get_event_loop().run_until_complete(execute_command(conf, api_method_name, params)) asyncio.get_event_loop().run_until_complete(execute_command(conf, api_method_name, params))
elif args.group is not None: elif args.group is not None:

View file

@ -1,3 +1,5 @@
DEFAULT_PAGE_SIZE = 20
NULL_HASH32 = b'\x00'*32 NULL_HASH32 = b'\x00'*32
CENT = 1000000 CENT = 1000000

View file

@ -19,40 +19,12 @@ from lbry.blockchain import Transaction, Output, dewies_to_lbc, dict_values_to_l
from lbry.stream.managed_stream import ManagedStream from lbry.stream.managed_stream import ManagedStream
from lbry.event import EventController, EventStream from lbry.event import EventController, EventStream
from lbry.crypto.hash import hex_str_to_hash from lbry.crypto.hash import hex_str_to_hash
from lbry.constants import DEFAULT_PAGE_SIZE
from .base import Service from .base import Service
from .json_encoder import Paginated from .json_encoder import Paginated
DEFAULT_PAGE_SIZE = 20
async def paginate_rows(get_records: Callable, page: Optional[int], page_size: Optional[int], **constraints):
page = max(1, page or 1)
page_size = max(1, page_size or DEFAULT_PAGE_SIZE)
constraints.update({
"offset": page_size * (page - 1),
"limit": page_size
})
return Paginated(await get_records(**constraints), page, page_size)
def paginate_list(items: List, page: Optional[int], page_size: Optional[int]):
page = max(1, page or 1)
page_size = max(1, page_size or DEFAULT_PAGE_SIZE)
total_items = len(items)
offset = page_size * (page - 1)
subitems = []
if offset <= total_items:
subitems = items[offset:offset+page_size]
return {
"items": subitems,
"total_pages": int((total_items + (page_size - 1)) / page_size),
"total_items": total_items,
"page": page, "page_size": page_size
}
StrOrList = Union[str, list] StrOrList = Union[str, list]
Address = Dict Address = Dict
@ -723,8 +695,8 @@ class API:
""" """
if wallet_id: if wallet_id:
return paginate_list([self.wallets.get_wallet_or_error(wallet_id)], 1, 1) return Paginated.from_list([self.wallets[wallet_id]], 1, 1)
return paginate_list(self.wallets.wallets, **pagination_kwargs) return Paginated.from_list(list(self.wallets.wallets.values()), **pagination_kwargs)
async def wallet_reconnect(self): async def wallet_reconnect(self):
""" Reconnects ledger network client, applying new configurations. """ """ Reconnects ledger network client, applying new configurations. """
@ -733,6 +705,7 @@ class API:
async def wallet_create( async def wallet_create(
self, self,
wallet_id: str, # wallet file name wallet_id: str, # wallet file name
name: str = "", #
skip_on_startup=False, # don't add wallet to daemon_settings.yml skip_on_startup=False, # don't add wallet to daemon_settings.yml
create_account=False, # generates the default account create_account=False, # generates the default account
single_key=False # used with --create_account, creates single-key account single_key=False # used with --create_account, creates single-key account
@ -741,12 +714,12 @@ class API:
Create a new wallet. Create a new wallet.
Usage: Usage:
wallet create (<wallet_id> | --wallet_id=<wallet_id>) [--skip_on_startup] wallet create (<wallet_id> | --wallet_id=<wallet_id>) [--name=<name>]
[--create_account] [--single_key] [--skip_on_startup] [--create_account] [--single_key]
""" """
wallet = await self.wallets.create( wallet = await self.wallets.create(
wallet_id, create_account=create_account, single_key=single_key wallet_id, name=name, create_account=create_account, single_key=single_key
) )
if not skip_on_startup: if not skip_on_startup:
with self.service.conf.update_config() as c: with self.service.conf.update_config() as c:
@ -764,17 +737,7 @@ class API:
wallet add (<wallet_id> | --wallet_id=<wallet_id>) wallet add (<wallet_id> | --wallet_id=<wallet_id>)
""" """
wallet_path = os.path.join(self.conf.wallet_dir, 'wallets', wallet_id) return await self.wallets.load(wallet_id)
for wallet in self.wallets.wallets:
if wallet.id == wallet_id:
raise Exception(f"Wallet at path '{wallet_path}' is already loaded.")
if not os.path.exists(wallet_path):
raise Exception(f"Wallet at path '{wallet_path}' was not found.")
wallet = self.wallets.import_wallet(wallet_path)
if self.ledger.sync.network.is_connected:
for account in wallet.accounts:
await self.ledger.subscribe_account(account)
return wallet
async def wallet_remove( async def wallet_remove(
self, self,
@ -787,11 +750,7 @@ class API:
wallet remove (<wallet_id> | --wallet_id=<wallet_id>) wallet remove (<wallet_id> | --wallet_id=<wallet_id>)
""" """
wallet = self.wallets.get_wallet_or_error(wallet_id) return self.wallets.remove(wallet_id)
self.wallets.wallets.remove(wallet)
for account in wallet.accounts:
await self.ledger.unsubscribe_account(account)
return wallet
async def wallet_balance( async def wallet_balance(
self, self,
@ -945,9 +904,8 @@ class API:
kwargs = {'confirmations': confirmations, 'show_seed': include_seed} kwargs = {'confirmations': confirmations, 'show_seed': include_seed}
wallet = self.wallets.get_or_default(wallet_id) wallet = self.wallets.get_or_default(wallet_id)
if account_id: if account_id:
return paginate_list([await wallet.get_account_or_error(account_id).get_details(**kwargs)], 1, 1) return Paginated.from_list([wallet.accounts[account_id]], 1, 1)
else: return Paginated.from_list(list(wallet.accounts), **pagination_kwargs)
return paginate_list(await wallet.get_detailed_accounts(**kwargs), **pagination_kwargs)
async def account_balance( async def account_balance(
self, self,
@ -1018,14 +976,9 @@ class API:
""" """
wallet = self.wallets.get_or_default(wallet_id) wallet = self.wallets.get_or_default(wallet_id)
account = await wallet.accounts.generate(account_name, language, { return await wallet.accounts.generate(account_name, language, {
'name': SingleKey.name if single_key else HierarchicalDeterministic.name 'name': SingleKey.name if single_key else HierarchicalDeterministic.name
}) })
await wallet.save()
# TODO: fix
#if self.ledger.sync.network.is_connected:
# await self.ledger.sync.subscribe_account(account)
return account
async def account_remove( async def account_remove(
self, self,
@ -1064,7 +1017,7 @@ class API:
""" """
wallet = self.wallets.get_or_default(wallet_id) wallet = self.wallets.get_or_default(wallet_id)
account = wallet.get_account_or_error(account_id) account = wallet.accounts[account_id]
change_made = False change_made = False
if account.receiving.name == HierarchicalDeterministic.name: if account.receiving.name == HierarchicalDeterministic.name:
@ -1083,14 +1036,13 @@ class API:
account.name = new_name account.name = new_name
change_made = True change_made = True
if default and wallet.default_account != account: if default and wallet.accounts.default != account:
wallet.accounts.remove(account) wallet.accounts.set_default(account)
wallet.accounts.insert(0, account)
change_made = True change_made = True
if change_made: if change_made:
account.modified_on = time.time() account.modified_on = time.time()
await wallet.save() await wallet.notify_change('account.updated')
return account return account

View file

@ -4,7 +4,7 @@ from decimal import Decimal
from binascii import hexlify, unhexlify from binascii import hexlify, unhexlify
from datetime import datetime, date from datetime import datetime, date
from json import JSONEncoder from json import JSONEncoder
from typing import Iterator, Generic from typing import Iterator, Generic, Callable, Awaitable
from google.protobuf.message import DecodeError from google.protobuf.message import DecodeError
@ -15,6 +15,7 @@ from lbry.crypto.bip32 import PubKey
from lbry.blockchain.dewies import dewies_to_lbc from lbry.blockchain.dewies import dewies_to_lbc
from lbry.stream.managed_stream import ManagedStream from lbry.stream.managed_stream import ManagedStream
from lbry.db.database import Result, ResultType from lbry.db.database import Result, ResultType
from lbry.constants import DEFAULT_PAGE_SIZE
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -135,6 +136,30 @@ class Paginated(Generic[ResultType]):
self.page = page self.page = page
self.page_size = page_size self.page_size = page_size
@classmethod
def from_list(cls, items: list, page: int = None, page_size: int = None):
page = max(1, page or 1)
page_size = max(1, page_size or DEFAULT_PAGE_SIZE)
total_items = len(items)
offset = page_size * (page - 1)
subitems = []
if offset <= total_items:
subitems = items[offset:offset + page_size]
return cls(Result(subitems, total_items), page, page_size)
@classmethod
async def from_getter(
cls, get_records: Callable[..., Awaitable[Result]],
page: int = None, page_size: int = None, **constraints
):
page = max(1, page or 1)
page_size = max(1, page_size or DEFAULT_PAGE_SIZE)
constraints.update({
"offset": page_size * (page - 1),
"limit": page_size
})
return cls(await get_records(**constraints), page, page_size)
def __getitem__(self, item: int) -> ResultType: def __getitem__(self, item: int) -> ResultType:
return self.result[item] return self.result[item]

View file

@ -582,12 +582,12 @@ class CommandTestCase(IntegrationTestCase):
self.wallet = self.service.wallets.default self.wallet = self.service.wallets.default
self.account = self.wallet.accounts.default self.account = self.wallet.accounts.default
addresses = await self.account.ensure_address_gap() address = await self.account.receiving.get_or_create_usable_address()
self.ledger.conf.upload_dir = os.path.join(self.ledger.conf.data_dir, 'uploads') self.ledger.conf.upload_dir = os.path.join(self.ledger.conf.data_dir, 'uploads')
os.mkdir(self.ledger.conf.upload_dir) os.mkdir(self.ledger.conf.upload_dir)
await self.chain.send_to_address(addresses[0], '10.0') await self.chain.send_to_address(address, '10.0')
await self.generate(5) await self.generate(5)
async def asyncTearDown(self): async def asyncTearDown(self):
@ -642,6 +642,33 @@ class CommandTestCase(IntegrationTestCase):
await self.service.wait(tx) await self.service.wait(tx)
return self.sout(tx) return self.sout(tx)
async def wallet_list(self, *args, **kwargs):
return (await self.out(self.api.wallet_list(*args, **kwargs)))['items']
async def wallet_create(self, *args, **kwargs):
return await self.out(self.api.wallet_create(*args, **kwargs))
async def wallet_add(self, *args, **kwargs):
return await self.out(self.api.wallet_add(*args, **kwargs))
async def wallet_remove(self, *args, **kwargs):
return await self.out(self.api.wallet_remove(*args, **kwargs))
async def account_list(self, *args, **kwargs):
return (await self.out(self.api.account_list(*args, **kwargs)))['items']
async def account_create(self, *args, **kwargs):
return await self.out(self.api.account_create(*args, **kwargs))
async def account_add(self, *args, **kwargs):
return await self.out(self.api.account_add(*args, **kwargs))
async def account_set(self, *args, **kwargs):
return await self.out(self.api.account_set(*args, **kwargs))
async def account_remove(self, *args, **kwargs):
return await self.out(self.api.account_remove(*args, **kwargs))
def create_upload_file(self, data, prefix=None, suffix=None): def create_upload_file(self, data, prefix=None, suffix=None):
file_path = tempfile.mktemp( file_path = tempfile.mktemp(
prefix=prefix or "tmp", suffix=suffix or "", dir=self.ledger.conf.upload_dir prefix=prefix or "tmp", suffix=suffix or "", dir=self.ledger.conf.upload_dir

View file

@ -101,6 +101,9 @@ class WalletManager:
wallet.on_change.listen(lambda _: self.storage.save(wallet)) wallet.on_change.listen(lambda _: self.storage.save(wallet))
return wallet return wallet
def remove(self, wallet_id: str) -> Wallet:
return self.wallets.pop(wallet_id)
async def _report_state(self): async def _report_state(self):
try: try:
for account in self.accounts: for account in self.accounts:

View file

@ -438,6 +438,10 @@ class AccountListManager:
await self.wallet.notify_change('account.removed') await self.wallet.notify_change('account.removed')
return account return account
def set_default(self, account):
self._accounts.remove(account)
self._accounts.insert(0, account)
def get_or_none(self, account_id: str) -> Optional[Account]: def get_or_none(self, account_id: str) -> Optional[Account]:
if account_id is not None: if account_id is not None:
return self[account_id] return self[account_id]