forked from LBRYCommunity/lbry-sdk
Merge pull request #652 from lbryio/arg-parsing
Parse cli args from docstrings and add positional arguments
This commit is contained in:
commit
84bac4bab7
9 changed files with 600 additions and 318 deletions
|
@ -40,4 +40,5 @@ script:
|
||||||
- pip install mock pylint unqlite
|
- pip install mock pylint unqlite
|
||||||
- pylint lbrynet
|
- pylint lbrynet
|
||||||
- PYTHONPATH=. trial tests
|
- PYTHONPATH=. trial tests
|
||||||
|
- python -m unittest discover tests/integration
|
||||||
- rvm use 2.3.1 && gem install danger --version '~> 4.0' && danger
|
- rvm use 2.3.1 && gem install danger --version '~> 4.0' && danger
|
||||||
|
|
|
@ -12,10 +12,12 @@ at anytime.
|
||||||
* Prevent publish of files with size 0
|
* Prevent publish of files with size 0
|
||||||
* Add `dht_status` parameter to `status` to include bandwidth and peer info
|
* Add `dht_status` parameter to `status` to include bandwidth and peer info
|
||||||
*
|
*
|
||||||
|
* Positional and flag arguments in lbrynet-cli
|
||||||
|
*
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
*
|
* Changed keyword arguments in lbrynet-cli to use a -- prefix
|
||||||
*
|
* Using the help function in lbrynet-cli no longer requires lbrynet-daemon to be running
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
*
|
*
|
||||||
|
|
|
@ -990,18 +990,19 @@ class Daemon(AuthJSONRPCServer):
|
||||||
############################################################################
|
############################################################################
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
|
@AuthJSONRPCServer.flags(session_status="-s", dht_status="-d")
|
||||||
def jsonrpc_status(self, session_status=False, dht_status=False):
|
def jsonrpc_status(self, session_status=False, dht_status=False):
|
||||||
"""
|
"""
|
||||||
Return daemon status
|
Get daemon status
|
||||||
|
|
||||||
Args:
|
Usage:
|
||||||
'session_status' (optional): (bool) true to return session status,
|
status [-s] [-d]
|
||||||
default is false
|
|
||||||
'dht_status' (optional): (bool) true to return dht status,
|
Options:
|
||||||
default is false
|
-s : include session status in results
|
||||||
Returns:
|
-d : include dht network and peer status
|
||||||
(dict) Daemon status dictionary
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# on startup, the wallet or network won't be available but we still need this call to work
|
# on startup, the wallet or network won't be available but we still need this call to work
|
||||||
has_wallet = self.session and self.session.wallet and self.session.wallet.network
|
has_wallet = self.session and self.session.wallet and self.session.wallet.network
|
||||||
local_height = self.session.wallet.network.get_local_height() if has_wallet else 0
|
local_height = self.session.wallet.network.get_local_height() if has_wallet else 0
|
||||||
|
@ -1042,23 +1043,28 @@ class Daemon(AuthJSONRPCServer):
|
||||||
response['dht_status'] = self.session.dht_node.get_bandwidth_stats()
|
response['dht_status'] = self.session.dht_node.get_bandwidth_stats()
|
||||||
defer.returnValue(response)
|
defer.returnValue(response)
|
||||||
|
|
||||||
|
@AuthJSONRPCServer.deprecated('status')
|
||||||
def jsonrpc_get_best_blockhash(self):
|
def jsonrpc_get_best_blockhash(self):
|
||||||
"""
|
"""
|
||||||
DEPRECATED. Use `status blockchain_status=True` instead
|
DEPRECATED. Use `status blockchain_status=True` instead
|
||||||
"""
|
"""
|
||||||
|
|
||||||
d = self.jsonrpc_status()
|
d = self.jsonrpc_status()
|
||||||
d.addCallback(lambda x: self._render_response(
|
d.addCallback(lambda x: self._render_response(
|
||||||
x['blockchain_status']['best_blockhash']))
|
x['blockchain_status']['best_blockhash']))
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
@AuthJSONRPCServer.deprecated('status')
|
||||||
def jsonrpc_is_running(self):
|
def jsonrpc_is_running(self):
|
||||||
"""
|
"""
|
||||||
DEPRECATED. Use `status` instead
|
DEPRECATED. Use `status` instead
|
||||||
"""
|
"""
|
||||||
|
|
||||||
d = self.jsonrpc_status()
|
d = self.jsonrpc_status()
|
||||||
d.addCallback(lambda x: self._render_response(x['is_running']))
|
d.addCallback(lambda x: self._render_response(x['is_running']))
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
@AuthJSONRPCServer.deprecated('status')
|
||||||
def jsonrpc_daemon_status(self):
|
def jsonrpc_daemon_status(self):
|
||||||
"""
|
"""
|
||||||
DEPRECATED. Use `status` instead
|
DEPRECATED. Use `status` instead
|
||||||
|
@ -1094,14 +1100,17 @@ class Daemon(AuthJSONRPCServer):
|
||||||
d.addCallback(lambda x: self._render_response(x)) # is this necessary?
|
d.addCallback(lambda x: self._render_response(x)) # is this necessary?
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
@AuthJSONRPCServer.deprecated('status')
|
||||||
def jsonrpc_is_first_run(self):
|
def jsonrpc_is_first_run(self):
|
||||||
"""
|
"""
|
||||||
DEPRECATED. Use `status` instead
|
DEPRECATED. Use `status` instead
|
||||||
"""
|
"""
|
||||||
|
|
||||||
d = self.jsonrpc_status()
|
d = self.jsonrpc_status()
|
||||||
d.addCallback(lambda x: self._render_response(x['is_first_run']))
|
d.addCallback(lambda x: self._render_response(x['is_first_run']))
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
@AuthJSONRPCServer.deprecated('status')
|
||||||
def jsonrpc_get_lbry_session_info(self):
|
def jsonrpc_get_lbry_session_info(self):
|
||||||
"""
|
"""
|
||||||
DEPRECATED. Use `status` instead
|
DEPRECATED. Use `status` instead
|
||||||
|
@ -1115,10 +1124,12 @@ class Daemon(AuthJSONRPCServer):
|
||||||
}))
|
}))
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
@AuthJSONRPCServer.deprecated('status')
|
||||||
def jsonrpc_get_time_behind_blockchain(self):
|
def jsonrpc_get_time_behind_blockchain(self):
|
||||||
"""
|
"""
|
||||||
DEPRECATED. Use `status` instead
|
DEPRECATED. Use `status` instead
|
||||||
"""
|
"""
|
||||||
|
|
||||||
d = self.jsonrpc_status()
|
d = self.jsonrpc_status()
|
||||||
d.addCallback(lambda x: self._render_response(x['blockchain_status']['blocks_behind']))
|
d.addCallback(lambda x: self._render_response(x['blockchain_status']['blocks_behind']))
|
||||||
return d
|
return d
|
||||||
|
@ -1127,8 +1138,9 @@ class Daemon(AuthJSONRPCServer):
|
||||||
"""
|
"""
|
||||||
Get lbry version information
|
Get lbry version information
|
||||||
|
|
||||||
Args:
|
Usage:
|
||||||
None
|
version
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
(dict) Dictionary of lbry version information
|
(dict) Dictionary of lbry version information
|
||||||
{
|
{
|
||||||
|
@ -1153,8 +1165,9 @@ class Daemon(AuthJSONRPCServer):
|
||||||
"""
|
"""
|
||||||
Report a bug to slack
|
Report a bug to slack
|
||||||
|
|
||||||
Args:
|
Usage:
|
||||||
'message': (str) message to send
|
report_bug (<message> | --message=<message>)
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
(bool) true if successful
|
(bool) true if successful
|
||||||
"""
|
"""
|
||||||
|
@ -1168,6 +1181,7 @@ class Daemon(AuthJSONRPCServer):
|
||||||
)
|
)
|
||||||
return self._render_response(True)
|
return self._render_response(True)
|
||||||
|
|
||||||
|
@AuthJSONRPCServer.deprecated('settings_get')
|
||||||
def jsonrpc_get_settings(self):
|
def jsonrpc_get_settings(self):
|
||||||
"""
|
"""
|
||||||
DEPRECATED. Use `settings_get` instead.
|
DEPRECATED. Use `settings_get` instead.
|
||||||
|
@ -1178,12 +1192,16 @@ class Daemon(AuthJSONRPCServer):
|
||||||
"""
|
"""
|
||||||
Get daemon settings
|
Get daemon settings
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
settings_get
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
(dict) Dictionary of daemon settings
|
(dict) Dictionary of daemon settings
|
||||||
See ADJUSTABLE_SETTINGS in lbrynet/conf.py for full list of settings
|
See ADJUSTABLE_SETTINGS in lbrynet/conf.py for full list of settings
|
||||||
"""
|
"""
|
||||||
return self._render_response(conf.settings.get_adjustable_settings_dict())
|
return self._render_response(conf.settings.get_adjustable_settings_dict())
|
||||||
|
|
||||||
|
@AuthJSONRPCServer.deprecated('settings_set')
|
||||||
@AuthJSONRPCServer.auth_required
|
@AuthJSONRPCServer.auth_required
|
||||||
def jsonrpc_set_settings(self, **kwargs):
|
def jsonrpc_set_settings(self, **kwargs):
|
||||||
"""
|
"""
|
||||||
|
@ -1218,11 +1236,11 @@ class Daemon(AuthJSONRPCServer):
|
||||||
"""
|
"""
|
||||||
Return a useful message for an API command
|
Return a useful message for an API command
|
||||||
|
|
||||||
Args:
|
Usage:
|
||||||
'command'(optional): (str) command to retrieve documentation for
|
help [<command> | --command=<command>]
|
||||||
Returns:
|
|
||||||
(str) if given a command, returns documentation about that command
|
Options:
|
||||||
otherwise returns general help message
|
<command>, --command=<command> : command to retrieve documentation for
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if command is None:
|
if command is None:
|
||||||
|
@ -1248,28 +1266,32 @@ class Daemon(AuthJSONRPCServer):
|
||||||
"""
|
"""
|
||||||
Return a list of available commands
|
Return a list of available commands
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
commands
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
(list) list of available commands
|
(list) list of available commands
|
||||||
"""
|
"""
|
||||||
return self._render_response(sorted(
|
return self._render_response(sorted([command for command in self.callable_methods.keys()]))
|
||||||
[command for command in self.callable_methods.keys()
|
|
||||||
if 'DEPRECATED' not in getattr(self, "jsonrpc_" + command).__doc__]
|
|
||||||
))
|
|
||||||
|
|
||||||
|
@AuthJSONRPCServer.deprecated('wallet_balance')
|
||||||
def jsonrpc_get_balance(self, address=None, include_unconfirmed=False):
|
def jsonrpc_get_balance(self, address=None, include_unconfirmed=False):
|
||||||
"""
|
"""
|
||||||
DEPRECATED. Use `wallet_balance` instead.
|
DEPRECATED. Use `wallet_balance` instead.
|
||||||
"""
|
"""
|
||||||
return self.jsonrpc_wallet_balance(address, include_unconfirmed)
|
return self.jsonrpc_wallet_balance(address, include_unconfirmed)
|
||||||
|
|
||||||
|
@AuthJSONRPCServer.flags(include_unconfirmed='-u')
|
||||||
def jsonrpc_wallet_balance(self, address=None, include_unconfirmed=False):
|
def jsonrpc_wallet_balance(self, address=None, include_unconfirmed=False):
|
||||||
"""
|
"""
|
||||||
Return the balance of the wallet
|
Return the balance of the wallet
|
||||||
|
|
||||||
Args:
|
Usage:
|
||||||
'address' (optional): If address is provided only that balance will be given
|
wallet_balance [<address> | --address=<address>] [-u]
|
||||||
'include_unconfirmed' (optional): If set unconfirmed balance will be included in
|
|
||||||
the only takes effect when address is also provided.
|
Options:
|
||||||
|
<address> : If provided only the balance for this address will be given
|
||||||
|
-u : Include unconfirmed
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
(float) amount of lbry credits in wallet
|
(float) amount of lbry credits in wallet
|
||||||
|
@ -1280,6 +1302,7 @@ class Daemon(AuthJSONRPCServer):
|
||||||
return self._render_response(float(
|
return self._render_response(float(
|
||||||
self.session.wallet.get_address_balance(address, include_unconfirmed)))
|
self.session.wallet.get_address_balance(address, include_unconfirmed)))
|
||||||
|
|
||||||
|
@AuthJSONRPCServer.deprecated('daemon_stop')
|
||||||
def jsonrpc_stop(self):
|
def jsonrpc_stop(self):
|
||||||
"""
|
"""
|
||||||
DEPRECATED. Use `daemon_stop` instead.
|
DEPRECATED. Use `daemon_stop` instead.
|
||||||
|
@ -1291,6 +1314,9 @@ class Daemon(AuthJSONRPCServer):
|
||||||
"""
|
"""
|
||||||
Stop lbrynet-daemon
|
Stop lbrynet-daemon
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
daemon_stop
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
(string) Shutdown message
|
(string) Shutdown message
|
||||||
"""
|
"""
|
||||||
|
@ -1301,19 +1327,27 @@ class Daemon(AuthJSONRPCServer):
|
||||||
defer.returnValue(response)
|
defer.returnValue(response)
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
|
@AuthJSONRPCServer.flags(full_status='-f')
|
||||||
def jsonrpc_file_list(self, **kwargs):
|
def jsonrpc_file_list(self, **kwargs):
|
||||||
"""
|
"""
|
||||||
List files limited by optional filters
|
List files limited by optional filters
|
||||||
|
|
||||||
Args:
|
Usage:
|
||||||
'name' (optional): (str) filter files by lbry name,
|
file_list [--sd_hash=<sd_hash>] [--file_name=<file_name>] [--stream_hash=<stream_hash>]
|
||||||
'sd_hash' (optional): (str) filter files by sd hash,
|
[--claim_id=<claim_id>] [--outpoint=<outpoint>] [--rowid=<rowid>]
|
||||||
'file_name' (optional): (str) filter files by the name in the downloads folder,
|
[--name=<name>]
|
||||||
'stream_hash' (optional): (str) filter files by stream hash,
|
[-f]
|
||||||
'claim_id' (optional): (str) filter files by claim id,
|
|
||||||
'outpoint' (optional): (str) filter files by claim outpoint,
|
Options:
|
||||||
'rowid' (optional): (int) filter files by internal row id,
|
--sd_hash=<sd_hash> : get file with matching sd hash
|
||||||
'full_status': (optional): (bool) if true populate the 'message' and 'size' fields
|
--file_name=<file_name> : get file with matching file name in the
|
||||||
|
downloads folder
|
||||||
|
--stream_hash=<stream_hash> : get file with matching stream hash
|
||||||
|
--claim_id=<claim_id> : get file with matching claim id
|
||||||
|
--outpoint=<outpoint> : get file with matching claim outpoint
|
||||||
|
--rowid=<rowid> : get file with matching row id
|
||||||
|
--name=<name> : get file with matching associated name claim
|
||||||
|
-f : full status, populate the 'message' and 'size' fields
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
(list) List of files
|
(list) List of files
|
||||||
|
@ -1348,12 +1382,17 @@ class Daemon(AuthJSONRPCServer):
|
||||||
defer.returnValue(response)
|
defer.returnValue(response)
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
|
@AuthJSONRPCServer.flags(force='-f')
|
||||||
def jsonrpc_resolve_name(self, name, force=False):
|
def jsonrpc_resolve_name(self, name, force=False):
|
||||||
"""
|
"""
|
||||||
Resolve stream info from a LBRY name
|
Resolve stream info from a LBRY name
|
||||||
|
|
||||||
Args:
|
Usage:
|
||||||
'name': (str) name to look up, do not include lbry:// prefix
|
resolve_name <name> [-f]
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-f : force refresh and do not check cache
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
(dict) Metadata dictionary from name claim, None if the name is not
|
(dict) Metadata dictionary from name claim, None if the name is not
|
||||||
resolvable
|
resolvable
|
||||||
|
@ -1367,6 +1406,7 @@ class Daemon(AuthJSONRPCServer):
|
||||||
else:
|
else:
|
||||||
defer.returnValue(metadata)
|
defer.returnValue(metadata)
|
||||||
|
|
||||||
|
@AuthJSONRPCServer.deprecated('claim_show')
|
||||||
def jsonrpc_get_claim_info(self, **kwargs):
|
def jsonrpc_get_claim_info(self, **kwargs):
|
||||||
"""
|
"""
|
||||||
DEPRECATED. Use `claim_show` instead.
|
DEPRECATED. Use `claim_show` instead.
|
||||||
|
@ -1375,15 +1415,18 @@ class Daemon(AuthJSONRPCServer):
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
def jsonrpc_claim_show(self, name=None, txid=None, nout=None, claim_id=None):
|
def jsonrpc_claim_show(self, name=None, txid=None, nout=None, claim_id=None):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Resolve claim info from a LBRY name
|
Resolve claim info from a LBRY name
|
||||||
|
|
||||||
Args:
|
Usage:
|
||||||
'name': (str) name to look up, do not include lbry:// prefix
|
claim_show <name> [<txid> | --txid=<txid>] [<nout> | --nout=<nout>]
|
||||||
'txid'(optional): (str) if specified, look for claim with this txid
|
[<claim_id> | --claim_id=<claim_id>]
|
||||||
'nout'(optional): (int) if specified, look for claim with this nout
|
|
||||||
'claim_id'(optional): (str) if specified, look for claim with this claim_id
|
Options:
|
||||||
|
<txid>, --txid=<txid> : look for claim with this txid
|
||||||
|
<nout>, --nout=<nout> : look for claim with this nout
|
||||||
|
<claim_id>, --claim_id=<claim_id> : look for claim with this claim id
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
(dict) Dictionary contaning claim info, (bool) false if claim is not
|
(dict) Dictionary contaning claim info, (bool) false if claim is not
|
||||||
resolvable
|
resolvable
|
||||||
|
@ -1414,13 +1457,17 @@ class Daemon(AuthJSONRPCServer):
|
||||||
|
|
||||||
@AuthJSONRPCServer.auth_required
|
@AuthJSONRPCServer.auth_required
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
|
@AuthJSONRPCServer.flags(force='-f')
|
||||||
def jsonrpc_resolve(self, uri, force=False):
|
def jsonrpc_resolve(self, uri, force=False):
|
||||||
"""
|
"""
|
||||||
Resolve a LBRY URI
|
Resolve a LBRY URI
|
||||||
|
|
||||||
Args:
|
Usage:
|
||||||
'uri': (str) uri to download
|
resolve <uri> [-f]
|
||||||
'force'(optional): (boolean) set to true to ignore cache and force refresh
|
|
||||||
|
Options:
|
||||||
|
-f : force refresh and ignore cache
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
None if nothing can be resolved, otherwise:
|
None if nothing can be resolved, otherwise:
|
||||||
If uri resolves to a channel or a claim in a channel:
|
If uri resolves to a channel or a claim in a channel:
|
||||||
|
@ -1502,11 +1549,15 @@ class Daemon(AuthJSONRPCServer):
|
||||||
"""
|
"""
|
||||||
Download stream from a LBRY name.
|
Download stream from a LBRY name.
|
||||||
|
|
||||||
Args:
|
Usage:
|
||||||
'uri': (str) lbry uri to download
|
get <uri> [<file_name> | --file_name=<file_name>] [<timeout> | --timeout=<timeout>]
|
||||||
'file_name'(optional): (str) a user specified name for the downloaded file
|
[<download_directory> | --download_directory=<download_directory>]
|
||||||
'timeout'(optional): (int) download timeout in number of seconds
|
|
||||||
'download_directory'(optional): (str) path to directory where file will be saved
|
Options:
|
||||||
|
<file_name> : specified name for the downloaded file
|
||||||
|
<timeout> : download timeout in number of seconds
|
||||||
|
<download_directory> : path to directory where file will be saved
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
(dict) Dictionary contaning information about the stream
|
(dict) Dictionary contaning information about the stream
|
||||||
{
|
{
|
||||||
|
@ -1568,6 +1619,7 @@ class Daemon(AuthJSONRPCServer):
|
||||||
response = yield self._render_response(result)
|
response = yield self._render_response(result)
|
||||||
defer.returnValue(response)
|
defer.returnValue(response)
|
||||||
|
|
||||||
|
@AuthJSONRPCServer.deprecated('file_set_status')
|
||||||
@AuthJSONRPCServer.auth_required
|
@AuthJSONRPCServer.auth_required
|
||||||
def jsonrpc_stop_lbry_file(self, **kwargs):
|
def jsonrpc_stop_lbry_file(self, **kwargs):
|
||||||
"""
|
"""
|
||||||
|
@ -1575,6 +1627,7 @@ class Daemon(AuthJSONRPCServer):
|
||||||
"""
|
"""
|
||||||
return self.jsonrpc_file_set_status(status='stop', **kwargs)
|
return self.jsonrpc_file_set_status(status='stop', **kwargs)
|
||||||
|
|
||||||
|
@AuthJSONRPCServer.deprecated('file_set_status')
|
||||||
@AuthJSONRPCServer.auth_required
|
@AuthJSONRPCServer.auth_required
|
||||||
def jsonrpc_start_lbry_file(self, **kwargs):
|
def jsonrpc_start_lbry_file(self, **kwargs):
|
||||||
"""
|
"""
|
||||||
|
@ -1588,11 +1641,22 @@ class Daemon(AuthJSONRPCServer):
|
||||||
"""
|
"""
|
||||||
Start or stop downloading a file
|
Start or stop downloading a file
|
||||||
|
|
||||||
Args:
|
Usage:
|
||||||
'status': (str) "start" or "stop"
|
file_set_status <status> [--sd_hash=<sd_hash>] [--file_name=<file_name>]
|
||||||
'name' (optional): (str) start file by lbry name,
|
[--stream_hash=<stream_hash>] [--claim_id=<claim_id>]
|
||||||
'sd_hash' (optional): (str) start file by the hash in the name claim,
|
[--outpoint=<outpoint>] [--rowid=<rowid>]
|
||||||
'file_name' (optional): (str) start file by its name in the downloads folder,
|
[--name=<name>]
|
||||||
|
|
||||||
|
Options:
|
||||||
|
--sd_hash=<sd_hash> : set status of file with matching sd hash
|
||||||
|
--file_name=<file_name> : set status of file with matching file name in the
|
||||||
|
downloads folder
|
||||||
|
--stream_hash=<stream_hash> : set status of file with matching stream hash
|
||||||
|
--claim_id=<claim_id> : set status of file with matching claim id
|
||||||
|
--outpoint=<outpoint> : set status of file with matching claim outpoint
|
||||||
|
--rowid=<rowid> : set status of file with matching row id
|
||||||
|
--name=<name> : set status of file with matching associated name claim
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
(str) Confirmation message
|
(str) Confirmation message
|
||||||
"""
|
"""
|
||||||
|
@ -1618,21 +1682,28 @@ class Daemon(AuthJSONRPCServer):
|
||||||
|
|
||||||
@AuthJSONRPCServer.auth_required
|
@AuthJSONRPCServer.auth_required
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
|
@AuthJSONRPCServer.flags(delete_target_file='-f', delete_all='-a')
|
||||||
def jsonrpc_file_delete(self, delete_target_file=True, delete_all=False, **kwargs):
|
def jsonrpc_file_delete(self, delete_target_file=True, delete_all=False, **kwargs):
|
||||||
"""
|
"""
|
||||||
Delete a lbry file
|
Delete a LBRY file
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
file_delete [-a | -f] [--sd_hash=<sd_hash>] [--file_name=<file_name>]
|
||||||
|
[--stream_hash=<stream_hash>] [--claim_id=<claim_id>]
|
||||||
|
[--outpoint=<outpoint>] [--rowid=<rowid>]
|
||||||
|
[--name=<name>]
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-a : delete file from downloads and delete stored blobs
|
||||||
|
-f : delete only from downloads, do not delete blobs
|
||||||
|
--sd_hash=<sd_hash> : delete by file sd hash
|
||||||
|
--file_name<file_name> : delete by file name in downloads folder
|
||||||
|
--stream_hash=<stream_hash> : delete by file stream hash
|
||||||
|
--claim_id=<claim_id> : delete by file claim id
|
||||||
|
--outpoint=<outpoint> : delete by file claim outpoint
|
||||||
|
--rowid=<rowid> : delete by file row id
|
||||||
|
--name=<name> : delete by associated name claim of file
|
||||||
|
|
||||||
Args:
|
|
||||||
'name' (optional): (str) delete file by lbry name,
|
|
||||||
'sd_hash' (optional): (str) delete file by sd hash,
|
|
||||||
'file_name' (optional): (str) delete file by the name in the downloads folder,
|
|
||||||
'stream_hash' (optional): (str) delete file by stream hash,
|
|
||||||
'claim_id' (optional): (str) delete file by claim ID,
|
|
||||||
'outpoint' (optional): (str) delete file by claim outpoint,
|
|
||||||
'rowid': (optional): (int) delete file by rowid in the file manager
|
|
||||||
'delete_target_file' (optional): (bool) delete file from downloads folder,
|
|
||||||
defaults to true if false only the blobs and
|
|
||||||
db entries will be deleted
|
|
||||||
Returns:
|
Returns:
|
||||||
(bool) true if deletion was successful
|
(bool) true if deletion was successful
|
||||||
"""
|
"""
|
||||||
|
@ -1663,6 +1734,7 @@ class Daemon(AuthJSONRPCServer):
|
||||||
response = yield self._render_response(result)
|
response = yield self._render_response(result)
|
||||||
defer.returnValue(response)
|
defer.returnValue(response)
|
||||||
|
|
||||||
|
@AuthJSONRPCServer.deprecated('stream_cost_estimate')
|
||||||
def jsonrpc_get_est_cost(self, **kwargs):
|
def jsonrpc_get_est_cost(self, **kwargs):
|
||||||
"""
|
"""
|
||||||
DEPRECATED. Use `stream_cost_estimate` instead
|
DEPRECATED. Use `stream_cost_estimate` instead
|
||||||
|
@ -1674,10 +1746,13 @@ class Daemon(AuthJSONRPCServer):
|
||||||
"""
|
"""
|
||||||
Get estimated cost for a lbry stream
|
Get estimated cost for a lbry stream
|
||||||
|
|
||||||
Args:
|
Usage:
|
||||||
'name': (str) lbry name
|
stream_cost_estimate <uri> [<size> | --size=<size>]
|
||||||
'size' (optional): (int) stream size, in bytes. if provided an sd blob
|
|
||||||
won't be downloaded.
|
Options:
|
||||||
|
<size>, --size=<size> : stream size in bytes. if provided an sd blob won't be
|
||||||
|
downloaded.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
(float) Estimated cost in lbry credits, returns None if uri is not
|
(float) Estimated cost in lbry credits, returns None if uri is not
|
||||||
resolveable
|
resolveable
|
||||||
|
@ -1690,11 +1765,11 @@ class Daemon(AuthJSONRPCServer):
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
def jsonrpc_channel_new(self, channel_name, amount):
|
def jsonrpc_channel_new(self, channel_name, amount):
|
||||||
"""
|
"""
|
||||||
Generate a publisher key and create a new certificate claim
|
Generate a publisher key and create a new '@' prefixed certificate claim
|
||||||
|
|
||||||
Args:
|
Usage:
|
||||||
'channel_name': (str) '@' prefixed name
|
channel_new (<channel_name> | --channel_name=<channel_name>)
|
||||||
'amount': (float) amount to claim name
|
(<amount> | --amount=<amount>)
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
(dict) Dictionary containing result of the claim
|
(dict) Dictionary containing result of the claim
|
||||||
|
@ -1732,6 +1807,9 @@ class Daemon(AuthJSONRPCServer):
|
||||||
"""
|
"""
|
||||||
Get my channels
|
Get my channels
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
channel_list_mine
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
(list) ClaimDict
|
(list) ClaimDict
|
||||||
"""
|
"""
|
||||||
|
@ -1756,38 +1834,48 @@ class Daemon(AuthJSONRPCServer):
|
||||||
'description'
|
'description'
|
||||||
'author'
|
'author'
|
||||||
'language'
|
'language'
|
||||||
'license',
|
'license'
|
||||||
'nsfw'
|
'nsfw'
|
||||||
|
|
||||||
Metadata can be set by either using the metadata argument or by setting individual arguments
|
Metadata can be set by either using the metadata argument or by setting individual arguments
|
||||||
fee, title, description, author, language, license, license_url, thumbnail, preview, nsfw,
|
fee, title, description, author, language, license, license_url, thumbnail, preview, nsfw,
|
||||||
or sources. Individual arguments will overwrite the fields specified in metadata argument.
|
or sources. Individual arguments will overwrite the fields specified in metadata argument.
|
||||||
|
|
||||||
Args:
|
Usage:
|
||||||
'name': (str) name to be claimed
|
publish (<name> | --name=<name>) (<bid> | --bid=<bid>) [--metadata=<metadata>]
|
||||||
'bid': (float) amount of credits to commit in this claim,
|
[--file_path=<file_path>] [--fee=<fee>] [--title=<title>]
|
||||||
'metadata'(optional): (dict) Metadata to associate with the claim.
|
[--description=<description>] [--author=<author>] [--language=<language>]
|
||||||
'file_path'(optional): (str) path to file to be associated with name. If provided,
|
[--license=<license>] [--license_url=<license_url>] [--thumbnail=<thumbnail>]
|
||||||
a lbry stream of this file will be used in 'sources'.
|
[--preview=<preview>] [--nsfw=<nsfw>] [--sources=<sources>]
|
||||||
If no path is given but a metadata dict is provided, the source
|
[--channel_name=<channel_name>] [--channel_id=<channel_id>]
|
||||||
from the given metadata will be used.
|
|
||||||
'fee'(optional): (dict) Dictionary representing key fee to download content:
|
Options:
|
||||||
{currency_symbol: {'amount': float, 'address': str, optional}}
|
--metadata=<metadata> : ClaimDict to associate with the claim.
|
||||||
supported currencies: LBC, USD, BTC
|
--file_path=<file_path> : path to file to be associated with name. If provided,
|
||||||
If an address is not provided a new one will be automatically
|
a lbry stream of this file will be used in 'sources'.
|
||||||
generated. Default fee is zero.
|
If no path is given but a metadata dict is provided,
|
||||||
'title'(optional): (str) title of the file
|
the source from the given metadata will be used.
|
||||||
'description'(optional): (str) description of the file
|
--fee=<fee> : Dictionary representing key fee to download content:
|
||||||
'author'(optional): (str) author of the file
|
{currency_symbol: {'amount': float,
|
||||||
'language'(optional): (str), language code
|
'address': str, optional}}
|
||||||
'license'(optional): (str) license for the file
|
supported currencies: LBC, USD, BTC
|
||||||
'license_url'(optional): (str) URL to license
|
If an address is not provided a new one will be
|
||||||
'thumbnail'(optional): (str) thumbnail URL for the file
|
automatically generated. Default fee is zero.
|
||||||
'preview'(optional): (str) preview URL for the file
|
--title=<title> : title of the publication
|
||||||
'nsfw'(optional): (bool) True if not safe for work
|
--description=<description> : description of the publication
|
||||||
'sources'(optional): (dict){'lbry_sd_hash':sd_hash} specifies sd hash of file
|
--author=<author> : author of the publication
|
||||||
'channel_name' (optional): (str) name of the publisher channel
|
--language=<language> : language of the publication
|
||||||
'channel_id' (optional): (str) claim id of the publisher channel
|
--license=<license> : publication license
|
||||||
|
--license_url=<license_url> : publication license url
|
||||||
|
--thumbnail=<thumbnail> : thumbnail url
|
||||||
|
--preview=<preview> : preview url
|
||||||
|
--nsfw=<nsfw> : title of the publication
|
||||||
|
--sources=<sources> : {'lbry_sd_hash':sd_hash} specifies sd hash of file
|
||||||
|
--channel_name=<channel_name> : name of the publisher channel name in the wallet
|
||||||
|
--channel_id=<channel_id> : claim id of the publisher channel, does not check
|
||||||
|
for channel claim being in the wallet. This allows
|
||||||
|
publishing to a channel where only the certificate
|
||||||
|
private key is in the wallet.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
(dict) Dictionary containing result of the claim
|
(dict) Dictionary containing result of the claim
|
||||||
|
@ -1883,6 +1971,7 @@ class Daemon(AuthJSONRPCServer):
|
||||||
response = yield self._render_response(result)
|
response = yield self._render_response(result)
|
||||||
defer.returnValue(response)
|
defer.returnValue(response)
|
||||||
|
|
||||||
|
@AuthJSONRPCServer.deprecated('claim_abandon')
|
||||||
@AuthJSONRPCServer.auth_required
|
@AuthJSONRPCServer.auth_required
|
||||||
def jsonrpc_abandon_claim(self, **kwargs):
|
def jsonrpc_abandon_claim(self, **kwargs):
|
||||||
"""
|
"""
|
||||||
|
@ -1896,8 +1985,9 @@ class Daemon(AuthJSONRPCServer):
|
||||||
"""
|
"""
|
||||||
Abandon a name and reclaim credits from the claim
|
Abandon a name and reclaim credits from the claim
|
||||||
|
|
||||||
Args:
|
Usage:
|
||||||
'claim_id': (str) claim_id of claim
|
claim_abandon (<claim_id> | --claim_id=<claim_id>)
|
||||||
|
|
||||||
Return:
|
Return:
|
||||||
(dict) Dictionary containing result of the claim
|
(dict) Dictionary containing result of the claim
|
||||||
{
|
{
|
||||||
|
@ -1919,18 +2009,22 @@ class Daemon(AuthJSONRPCServer):
|
||||||
response = yield self._render_response(err)
|
response = yield self._render_response(err)
|
||||||
defer.returnValue(response)
|
defer.returnValue(response)
|
||||||
|
|
||||||
|
@AuthJSONRPCServer.deprecated('claim_abandon')
|
||||||
@AuthJSONRPCServer.auth_required
|
@AuthJSONRPCServer.auth_required
|
||||||
def jsonrpc_abandon_name(self, **kwargs):
|
def jsonrpc_abandon_name(self, **kwargs):
|
||||||
"""
|
"""
|
||||||
DEPRECATED. Use `claim_abandon` instead
|
DEPRECATED. Use `claim_abandon` instead
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return self.jsonrpc_claim_abandon(**kwargs)
|
return self.jsonrpc_claim_abandon(**kwargs)
|
||||||
|
|
||||||
|
@AuthJSONRPCServer.deprecated('claim_support_new')
|
||||||
@AuthJSONRPCServer.auth_required
|
@AuthJSONRPCServer.auth_required
|
||||||
def jsonrpc_support_claim(self, **kwargs):
|
def jsonrpc_support_claim(self, **kwargs):
|
||||||
"""
|
"""
|
||||||
DEPRECATED. Use `claim_abandon` instead
|
DEPRECATED. Use `claim_support_new` instead
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return self.jsonrpc_claim_new_support(**kwargs)
|
return self.jsonrpc_claim_new_support(**kwargs)
|
||||||
|
|
||||||
@AuthJSONRPCServer.auth_required
|
@AuthJSONRPCServer.auth_required
|
||||||
|
@ -1939,10 +2033,10 @@ class Daemon(AuthJSONRPCServer):
|
||||||
"""
|
"""
|
||||||
Support a name claim
|
Support a name claim
|
||||||
|
|
||||||
Args:
|
Usage:
|
||||||
'name': (str) name
|
claim_new_support (<name> | --name=<name>) (<claim_id> | --claim_id=<claim_id>)
|
||||||
'claim_id': (str) claim ID of claim to support
|
(<amount> | --amount<amount>)
|
||||||
'amount': (float) amount to support by
|
|
||||||
Return:
|
Return:
|
||||||
(dict) Dictionary containing result of the claim
|
(dict) Dictionary containing result of the claim
|
||||||
{
|
{
|
||||||
|
@ -1956,7 +2050,7 @@ class Daemon(AuthJSONRPCServer):
|
||||||
self.analytics_manager.send_claim_action('new_support')
|
self.analytics_manager.send_claim_action('new_support')
|
||||||
defer.returnValue(result)
|
defer.returnValue(result)
|
||||||
|
|
||||||
# TODO: merge this into claim_list
|
@AuthJSONRPCServer.deprecated('claim_list_mine')
|
||||||
@AuthJSONRPCServer.auth_required
|
@AuthJSONRPCServer.auth_required
|
||||||
def jsonrpc_get_my_claim(self, name):
|
def jsonrpc_get_my_claim(self, name):
|
||||||
"""
|
"""
|
||||||
|
@ -1974,6 +2068,7 @@ class Daemon(AuthJSONRPCServer):
|
||||||
d.addCallback(lambda r: self._render_response(r))
|
d.addCallback(lambda r: self._render_response(r))
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
@AuthJSONRPCServer.deprecated('claim_list_mine')
|
||||||
@AuthJSONRPCServer.auth_required
|
@AuthJSONRPCServer.auth_required
|
||||||
def jsonrpc_get_name_claims(self):
|
def jsonrpc_get_name_claims(self):
|
||||||
"""
|
"""
|
||||||
|
@ -1987,8 +2082,9 @@ class Daemon(AuthJSONRPCServer):
|
||||||
"""
|
"""
|
||||||
List my name claims
|
List my name claims
|
||||||
|
|
||||||
Args:
|
Usage:
|
||||||
None
|
claim_list_mine
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
(list) List of name claims owned by user
|
(list) List of name claims owned by user
|
||||||
[
|
[
|
||||||
|
@ -2016,12 +2112,14 @@ class Daemon(AuthJSONRPCServer):
|
||||||
d.addCallback(lambda claims: self._render_response(claims))
|
d.addCallback(lambda claims: self._render_response(claims))
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
@AuthJSONRPCServer.deprecated('claim_list')
|
||||||
def jsonrpc_get_claims_for_name(self, **kwargs):
|
def jsonrpc_get_claims_for_name(self, **kwargs):
|
||||||
"""
|
"""
|
||||||
DEPRECATED. Use `claim_list` instead.
|
DEPRECATED. Use `claim_list` instead.
|
||||||
"""
|
"""
|
||||||
return self.jsonrpc_claim_list(**kwargs)
|
return self.jsonrpc_claim_list(**kwargs)
|
||||||
|
|
||||||
|
@AuthJSONRPCServer.deprecated('claim_list')
|
||||||
def jsonrpc_get_claims_for_tx(self, **kwargs):
|
def jsonrpc_get_claims_for_tx(self, **kwargs):
|
||||||
"""
|
"""
|
||||||
DEPRECATED. Use `claim_list` instead.
|
DEPRECATED. Use `claim_list` instead.
|
||||||
|
@ -2033,8 +2131,9 @@ class Daemon(AuthJSONRPCServer):
|
||||||
"""
|
"""
|
||||||
Get claims for a name
|
Get claims for a name
|
||||||
|
|
||||||
Args:
|
Usage:
|
||||||
'name': (str) search for claims on this name
|
claim_list (<name> | --name=<name>)
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
(dict) State of claims assigned for the name
|
(dict) State of claims assigned for the name
|
||||||
{
|
{
|
||||||
|
@ -2060,6 +2159,7 @@ class Daemon(AuthJSONRPCServer):
|
||||||
claims = yield self.session.wallet.get_claims_for_name(name)
|
claims = yield self.session.wallet.get_claims_for_name(name)
|
||||||
defer.returnValue(claims)
|
defer.returnValue(claims)
|
||||||
|
|
||||||
|
@AuthJSONRPCServer.deprecated('transaction_list')
|
||||||
@AuthJSONRPCServer.auth_required
|
@AuthJSONRPCServer.auth_required
|
||||||
def jsonrpc_get_transaction_history(self):
|
def jsonrpc_get_transaction_history(self):
|
||||||
"""
|
"""
|
||||||
|
@ -2072,8 +2172,9 @@ class Daemon(AuthJSONRPCServer):
|
||||||
"""
|
"""
|
||||||
List transactions belonging to wallet
|
List transactions belonging to wallet
|
||||||
|
|
||||||
Args:
|
Usage:
|
||||||
None
|
transaction_list
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
(list) List of transactions
|
(list) List of transactions
|
||||||
"""
|
"""
|
||||||
|
@ -2082,6 +2183,7 @@ class Daemon(AuthJSONRPCServer):
|
||||||
d.addCallback(lambda r: self._render_response(r))
|
d.addCallback(lambda r: self._render_response(r))
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
@AuthJSONRPCServer.deprecated('transaction_show')
|
||||||
def jsonrpc_get_transaction(self, txid):
|
def jsonrpc_get_transaction(self, txid):
|
||||||
"""
|
"""
|
||||||
DEPRECATED. Use `transaction_show` instead
|
DEPRECATED. Use `transaction_show` instead
|
||||||
|
@ -2092,8 +2194,9 @@ class Daemon(AuthJSONRPCServer):
|
||||||
"""
|
"""
|
||||||
Get a decoded transaction from a txid
|
Get a decoded transaction from a txid
|
||||||
|
|
||||||
Args:
|
Usage:
|
||||||
'txid': (str) txid of transaction
|
transaction_show (<txid> | --txid=<txid>)
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
(dict) JSON formatted transaction
|
(dict) JSON formatted transaction
|
||||||
"""
|
"""
|
||||||
|
@ -2102,6 +2205,7 @@ class Daemon(AuthJSONRPCServer):
|
||||||
d.addCallback(lambda r: self._render_response(r))
|
d.addCallback(lambda r: self._render_response(r))
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
@AuthJSONRPCServer.deprecated('wallet_is_address_mine')
|
||||||
@AuthJSONRPCServer.auth_required
|
@AuthJSONRPCServer.auth_required
|
||||||
def jsonrpc_address_is_mine(self, address):
|
def jsonrpc_address_is_mine(self, address):
|
||||||
"""
|
"""
|
||||||
|
@ -2114,8 +2218,9 @@ class Daemon(AuthJSONRPCServer):
|
||||||
"""
|
"""
|
||||||
Checks if an address is associated with the current wallet.
|
Checks if an address is associated with the current wallet.
|
||||||
|
|
||||||
Args:
|
Usage:
|
||||||
'address': (str) address to check in base58
|
wallet_is_address_mine (<address> | --address=<address>)
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
(bool) true, if address is associated with current wallet
|
(bool) true, if address is associated with current wallet
|
||||||
"""
|
"""
|
||||||
|
@ -2124,10 +2229,11 @@ class Daemon(AuthJSONRPCServer):
|
||||||
d.addCallback(lambda is_mine: self._render_response(is_mine))
|
d.addCallback(lambda is_mine: self._render_response(is_mine))
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
@AuthJSONRPCServer.deprecated('wallet_public_key')
|
||||||
@AuthJSONRPCServer.auth_required
|
@AuthJSONRPCServer.auth_required
|
||||||
def jsonrpc_get_public_key_from_wallet(self, wallet):
|
def jsonrpc_get_public_key_from_wallet(self, wallet):
|
||||||
"""
|
"""
|
||||||
DEPRECATED. Use `wallet_is_address_mine` instead
|
DEPRECATED. Use `wallet_public_key` instead
|
||||||
"""
|
"""
|
||||||
return self.jsonrpc_wallet_public_key(wallet)
|
return self.jsonrpc_wallet_public_key(wallet)
|
||||||
|
|
||||||
|
@ -2136,8 +2242,9 @@ class Daemon(AuthJSONRPCServer):
|
||||||
"""
|
"""
|
||||||
Get public key from wallet address
|
Get public key from wallet address
|
||||||
|
|
||||||
Args:
|
Usage:
|
||||||
'address': (str) wallet address in base58
|
wallet_public_key (<address> | --address=<address>)
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
(list) list of public keys associated with address.
|
(list) list of public keys associated with address.
|
||||||
Could contain more than one public key if multisig.
|
Could contain more than one public key if multisig.
|
||||||
|
@ -2153,8 +2260,9 @@ class Daemon(AuthJSONRPCServer):
|
||||||
"""
|
"""
|
||||||
List wallet addresses
|
List wallet addresses
|
||||||
|
|
||||||
Args:
|
Usage:
|
||||||
None
|
wallet_list
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
List of wallet addresses
|
List of wallet addresses
|
||||||
"""
|
"""
|
||||||
|
@ -2163,6 +2271,7 @@ class Daemon(AuthJSONRPCServer):
|
||||||
response = yield self._render_response(addresses)
|
response = yield self._render_response(addresses)
|
||||||
defer.returnValue(response)
|
defer.returnValue(response)
|
||||||
|
|
||||||
|
@AuthJSONRPCServer.deprecated('wallet_new_address')
|
||||||
@AuthJSONRPCServer.auth_required
|
@AuthJSONRPCServer.auth_required
|
||||||
def jsonrpc_get_new_address(self):
|
def jsonrpc_get_new_address(self):
|
||||||
"""
|
"""
|
||||||
|
@ -2175,8 +2284,9 @@ class Daemon(AuthJSONRPCServer):
|
||||||
"""
|
"""
|
||||||
Generate a new wallet address
|
Generate a new wallet address
|
||||||
|
|
||||||
Args:
|
Usage:
|
||||||
None
|
wallet_new_address
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
(str) New wallet address in base58
|
(str) New wallet address in base58
|
||||||
"""
|
"""
|
||||||
|
@ -2196,8 +2306,9 @@ class Daemon(AuthJSONRPCServer):
|
||||||
Return an address containing no balance, will create
|
Return an address containing no balance, will create
|
||||||
a new address if there is none.
|
a new address if there is none.
|
||||||
|
|
||||||
Args:
|
Usage:
|
||||||
None
|
wallet_unused_address
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
(str) Unused wallet address in base58
|
(str) Unused wallet address in base58
|
||||||
"""
|
"""
|
||||||
|
@ -2215,11 +2326,11 @@ class Daemon(AuthJSONRPCServer):
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
def jsonrpc_send_amount_to_address(self, amount, address):
|
def jsonrpc_send_amount_to_address(self, amount, address):
|
||||||
"""
|
"""
|
||||||
Send credits to an address
|
Queue a payment of credits to an address
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
send_amount_to_address (<amount> | --amount=<amount>) (<address> | --address=<address>)
|
||||||
|
|
||||||
Args:
|
|
||||||
'amount': (float) the amount to send
|
|
||||||
'address': (str) the address of the recipient in base58
|
|
||||||
Returns:
|
Returns:
|
||||||
(bool) true if payment successfully scheduled
|
(bool) true if payment successfully scheduled
|
||||||
"""
|
"""
|
||||||
|
@ -2231,6 +2342,7 @@ class Daemon(AuthJSONRPCServer):
|
||||||
self.analytics_manager.send_credits_sent()
|
self.analytics_manager.send_credits_sent()
|
||||||
defer.returnValue(True)
|
defer.returnValue(True)
|
||||||
|
|
||||||
|
@AuthJSONRPCServer.deprecated('block_show')
|
||||||
def jsonrpc_get_block(self, **kwargs):
|
def jsonrpc_get_block(self, **kwargs):
|
||||||
"""
|
"""
|
||||||
DEPRECATED. Use `block_show` instead
|
DEPRECATED. Use `block_show` instead
|
||||||
|
@ -2241,8 +2353,13 @@ class Daemon(AuthJSONRPCServer):
|
||||||
"""
|
"""
|
||||||
Get contents of a block
|
Get contents of a block
|
||||||
|
|
||||||
Args:
|
Usage:
|
||||||
'blockhash': (str) hash of the block to look up
|
block_show (<blockhash> | --blockhash=<blockhash>) | (<height> | --height=<height>)
|
||||||
|
|
||||||
|
Options:
|
||||||
|
<blockhash>, --blockhash=<blockhash> : hash of the block to look up
|
||||||
|
<height>, --height=<height> : height of the block to look up
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
(dict) Requested block
|
(dict) Requested block
|
||||||
"""
|
"""
|
||||||
|
@ -2259,6 +2376,7 @@ class Daemon(AuthJSONRPCServer):
|
||||||
d.addCallback(lambda r: self._render_response(r))
|
d.addCallback(lambda r: self._render_response(r))
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
@AuthJSONRPCServer.deprecated('descriptor_get')
|
||||||
@AuthJSONRPCServer.auth_required
|
@AuthJSONRPCServer.auth_required
|
||||||
def jsonrpc_download_descriptor(self, **kwargs):
|
def jsonrpc_download_descriptor(self, **kwargs):
|
||||||
"""
|
"""
|
||||||
|
@ -2266,6 +2384,7 @@ class Daemon(AuthJSONRPCServer):
|
||||||
"""
|
"""
|
||||||
return self.jsonrpc_descriptor_get(**kwargs)
|
return self.jsonrpc_descriptor_get(**kwargs)
|
||||||
|
|
||||||
|
@AuthJSONRPCServer.deprecated('blob_get')
|
||||||
@AuthJSONRPCServer.auth_required
|
@AuthJSONRPCServer.auth_required
|
||||||
def jsonrpc_descriptor_get(self, sd_hash, timeout=None, payment_rate_manager=None):
|
def jsonrpc_descriptor_get(self, sd_hash, timeout=None, payment_rate_manager=None):
|
||||||
"""
|
"""
|
||||||
|
@ -2289,15 +2408,20 @@ class Daemon(AuthJSONRPCServer):
|
||||||
"""
|
"""
|
||||||
Download and return a blob
|
Download and return a blob
|
||||||
|
|
||||||
Args:
|
Usage:
|
||||||
'blob_hash': (str) blob hash of blob to get
|
blob_get (<blob_hash> | --blob_hash=<blob_hash>) [--timeout=<timeout>]
|
||||||
'timeout'(optional): (int) timeout in number of seconds
|
[--encoding=<encoding>] [--payment_rate_manager=<payment_rate_manager>]
|
||||||
'encoding'(optional): (str) by default no attempt at decoding is made,
|
|
||||||
can be set to one of the following decoders:
|
Options:
|
||||||
'json'
|
--timeout=<timeout> : timeout in number of seconds
|
||||||
'payment_rate_manager'(optional): if not given the default payment rate manager
|
--encoding=<encoding> : by default no attempt at decoding is made,
|
||||||
will be used. supported alternative rate managers:
|
can be set to one of the
|
||||||
'only-free'
|
following decoders:
|
||||||
|
'json'
|
||||||
|
--payment_rate_manager=<payment_rate_manager> : if not given the default payment rate
|
||||||
|
manager will be used.
|
||||||
|
supported alternative rate managers:
|
||||||
|
'only-free'
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
(str) Success/Fail message or (dict) decoded data
|
(str) Success/Fail message or (dict) decoded data
|
||||||
|
@ -2327,8 +2451,9 @@ class Daemon(AuthJSONRPCServer):
|
||||||
"""
|
"""
|
||||||
Delete a blob
|
Delete a blob
|
||||||
|
|
||||||
Args:
|
Usage:
|
||||||
'blob_hash': (str) hash of blob to get
|
blob_delete (<blob_hash> | --blob_hash=<blob_hash)
|
||||||
|
t
|
||||||
Returns:
|
Returns:
|
||||||
(str) Success/fail message
|
(str) Success/fail message
|
||||||
"""
|
"""
|
||||||
|
@ -2345,6 +2470,7 @@ class Daemon(AuthJSONRPCServer):
|
||||||
response = yield self._render_response("Deleted %s" % blob_hash)
|
response = yield self._render_response("Deleted %s" % blob_hash)
|
||||||
defer.returnValue(response)
|
defer.returnValue(response)
|
||||||
|
|
||||||
|
@AuthJSONRPCServer.deprecated('peer_list')
|
||||||
def jsonrpc_get_peers_for_hash(self, blob_hash):
|
def jsonrpc_get_peers_for_hash(self, blob_hash):
|
||||||
"""
|
"""
|
||||||
DEPRECATED. Use `peer_list` instead
|
DEPRECATED. Use `peer_list` instead
|
||||||
|
@ -2355,9 +2481,12 @@ class Daemon(AuthJSONRPCServer):
|
||||||
"""
|
"""
|
||||||
Get peers for blob hash
|
Get peers for blob hash
|
||||||
|
|
||||||
Args:
|
Usage:
|
||||||
'blob_hash': (str) blob hash
|
peer_list (<blob_hash> | --blob_hash=<blob_hash>) [<timeout> | --timeout=<timeout>]
|
||||||
'timeout'(optional): (int) peer search timeout in seconds
|
|
||||||
|
Options:
|
||||||
|
<timeout>, --timeout=<timeout> : peer search timeout in seconds
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
(list) List of contacts
|
(list) List of contacts
|
||||||
"""
|
"""
|
||||||
|
@ -2369,6 +2498,7 @@ class Daemon(AuthJSONRPCServer):
|
||||||
d.addCallback(lambda r: self._render_response(r))
|
d.addCallback(lambda r: self._render_response(r))
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
@AuthJSONRPCServer.deprecated('blob_announce_all')
|
||||||
def jsonrpc_announce_all_blobs_to_dht(self):
|
def jsonrpc_announce_all_blobs_to_dht(self):
|
||||||
"""
|
"""
|
||||||
DEPRECATED. Use `blob_announce_all` instead.
|
DEPRECATED. Use `blob_announce_all` instead.
|
||||||
|
@ -2379,8 +2509,9 @@ class Daemon(AuthJSONRPCServer):
|
||||||
"""
|
"""
|
||||||
Announce all blobs to the DHT
|
Announce all blobs to the DHT
|
||||||
|
|
||||||
Args:
|
Usage:
|
||||||
None
|
blob_announce_all
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
(str) Success/fail message
|
(str) Success/fail message
|
||||||
"""
|
"""
|
||||||
|
@ -2394,8 +2525,9 @@ class Daemon(AuthJSONRPCServer):
|
||||||
"""
|
"""
|
||||||
Reflect a stream
|
Reflect a stream
|
||||||
|
|
||||||
Args:
|
Usage:
|
||||||
'sd_hash': (str) sd_hash of lbry file
|
reflect (<sd_hash> | --sd_hash=<sd_hash>)
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
(bool) true if successful
|
(bool) true if successful
|
||||||
"""
|
"""
|
||||||
|
@ -2406,6 +2538,7 @@ class Daemon(AuthJSONRPCServer):
|
||||||
yield reupload.reflect_stream(lbry_file)
|
yield reupload.reflect_stream(lbry_file)
|
||||||
defer.returnValue("Reflect success")
|
defer.returnValue("Reflect success")
|
||||||
|
|
||||||
|
@AuthJSONRPCServer.deprecated('blob_list')
|
||||||
def jsonrpc_get_blob_hashes(self):
|
def jsonrpc_get_blob_hashes(self):
|
||||||
"""
|
"""
|
||||||
DEPRECATED. Use `blob_list` instead
|
DEPRECATED. Use `blob_list` instead
|
||||||
|
@ -2461,6 +2594,7 @@ class Daemon(AuthJSONRPCServer):
|
||||||
response = yield self._render_response(blob_hashes_for_return)
|
response = yield self._render_response(blob_hashes_for_return)
|
||||||
defer.returnValue(response)
|
defer.returnValue(response)
|
||||||
|
|
||||||
|
@AuthJSONRPCServer.deprecated('blob_reflect_all')
|
||||||
def jsonrpc_reflect_all_blobs(self):
|
def jsonrpc_reflect_all_blobs(self):
|
||||||
"""
|
"""
|
||||||
DEPRECATED. Use `blob_reflect_all` instead
|
DEPRECATED. Use `blob_reflect_all` instead
|
||||||
|
@ -2471,8 +2605,9 @@ class Daemon(AuthJSONRPCServer):
|
||||||
"""
|
"""
|
||||||
Reflects all saved blobs
|
Reflects all saved blobs
|
||||||
|
|
||||||
Args:
|
Usage:
|
||||||
None
|
blob_reflect_all
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
(bool) true if successful
|
(bool) true if successful
|
||||||
"""
|
"""
|
||||||
|
@ -2487,10 +2622,13 @@ class Daemon(AuthJSONRPCServer):
|
||||||
"""
|
"""
|
||||||
Get stream availability for lbry uri
|
Get stream availability for lbry uri
|
||||||
|
|
||||||
Args:
|
Usage:
|
||||||
'uri' : (str) lbry uri
|
get_availability (<uri> | --uri=<uri>) [<sd_timeout> | --sd_timeout=<sd_timeout>]
|
||||||
'sd_timeout' (optional): (int) sd blob download timeout
|
[<peer_timeout> | --peer_timeout=<peer_timeout>]
|
||||||
'peer_timeout' (optional): (int) how long to look for peers
|
|
||||||
|
Options:
|
||||||
|
<sd_timeout>, --sd_timeout=<sd_timeout> : sd blob download timeout
|
||||||
|
<peer_timeout>, --peer_timeout=<peer_timeout> : how long to look for peers
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
(float) Peers per blob / total blobs
|
(float) Peers per blob / total blobs
|
||||||
|
@ -2554,6 +2692,7 @@ class Daemon(AuthJSONRPCServer):
|
||||||
response = yield self._render_response(mean_availability)
|
response = yield self._render_response(mean_availability)
|
||||||
defer.returnValue(response)
|
defer.returnValue(response)
|
||||||
|
|
||||||
|
@AuthJSONRPCServer.deprecated('status')
|
||||||
def jsonrpc_get_start_notice(self):
|
def jsonrpc_get_start_notice(self):
|
||||||
"""
|
"""
|
||||||
DEPRECATED.
|
DEPRECATED.
|
||||||
|
@ -2576,6 +2715,28 @@ class Daemon(AuthJSONRPCServer):
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@defer.inlineCallbacks
|
||||||
|
def jsonrpc_cli_test_command(self, pos_arg, pos_args=[], pos_arg2=None, pos_arg3=None):
|
||||||
|
"""
|
||||||
|
This command is only for testing the CLI argument parsing
|
||||||
|
Usage:
|
||||||
|
cli_test_command (<pos_arg> | --pos_arg=<pos_arg>)
|
||||||
|
[<pos_args>...] [--pos_arg2=<pos_arg2>]
|
||||||
|
[--pos_arg3=<pos_arg3>]
|
||||||
|
|
||||||
|
Options:
|
||||||
|
<pos_arg2>, --pos_arg2=<pos_arg2> : pos arg 2
|
||||||
|
<pos_arg3>, --pos_arg3=<pos_arg3> : pos arg 3
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
pos args
|
||||||
|
"""
|
||||||
|
out = (pos_arg, pos_args, pos_arg2, pos_arg3)
|
||||||
|
response = yield self._render_response(out)
|
||||||
|
defer.returnValue(response)
|
||||||
|
|
||||||
|
|
||||||
class _ResolveNameHelper(object):
|
class _ResolveNameHelper(object):
|
||||||
def __init__(self, daemon, name, force_refresh):
|
def __init__(self, daemon, name, force_refresh):
|
||||||
self.daemon = daemon
|
self.daemon = daemon
|
||||||
|
|
|
@ -1,23 +1,68 @@
|
||||||
import argparse
|
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import colorama
|
import colorama
|
||||||
|
from docopt import docopt
|
||||||
|
from collections import OrderedDict
|
||||||
from lbrynet import conf
|
from lbrynet import conf
|
||||||
from lbrynet.core import utils
|
from lbrynet.core import utils
|
||||||
from lbrynet.lbrynet_daemon.auth.client import JSONRPCException, LBRYAPIClient
|
from lbrynet.lbrynet_daemon.auth.client import JSONRPCException, LBRYAPIClient
|
||||||
from lbrynet.lbrynet_daemon.Daemon import LOADING_WALLET_CODE
|
from lbrynet.lbrynet_daemon.Daemon import LOADING_WALLET_CODE, Daemon
|
||||||
from jsonrpc.common import RPCError
|
from jsonrpc.common import RPCError
|
||||||
from urllib2 import URLError, HTTPError
|
from urllib2 import URLError, HTTPError
|
||||||
from httplib import UNAUTHORIZED
|
from httplib import UNAUTHORIZED
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def remove_brackets(key):
|
||||||
colorama.init()
|
if key.startswith("<") and key.endswith(">"):
|
||||||
parser = argparse.ArgumentParser(add_help=False)
|
return str(key[1:-1])
|
||||||
_, arguments = parser.parse_known_args()
|
return key
|
||||||
|
|
||||||
|
|
||||||
|
def set_flag_vals(flag_names, parsed_args):
|
||||||
|
kwargs = OrderedDict()
|
||||||
|
for key, arg in parsed_args.iteritems():
|
||||||
|
if arg is None:
|
||||||
|
continue
|
||||||
|
elif key.startswith("--"):
|
||||||
|
if remove_brackets(key[2:]) not in kwargs:
|
||||||
|
k = remove_brackets(key[2:])
|
||||||
|
kwargs[k] = guess_type(arg)
|
||||||
|
elif key in flag_names:
|
||||||
|
if remove_brackets(flag_names[key]) not in kwargs:
|
||||||
|
kwargs[remove_brackets(flag_names[key])] = guess_type(arg)
|
||||||
|
elif remove_brackets(key) not in kwargs:
|
||||||
|
kwargs[remove_brackets(key)] = guess_type(arg)
|
||||||
|
return kwargs
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
if len(sys.argv[1:]):
|
||||||
|
method, args = sys.argv[1], sys.argv[2:]
|
||||||
|
else:
|
||||||
|
print_help()
|
||||||
|
return
|
||||||
|
|
||||||
|
if method in ['help', '--help', '-h']:
|
||||||
|
if len(args) == 1:
|
||||||
|
print_help_for_command(args[0])
|
||||||
|
else:
|
||||||
|
print_help()
|
||||||
|
return
|
||||||
|
|
||||||
|
if method not in Daemon.callable_methods:
|
||||||
|
print_error("\"%s\" is not a valid command." % method)
|
||||||
|
return
|
||||||
|
|
||||||
|
fn = Daemon.callable_methods[method]
|
||||||
|
if hasattr(fn, "_flags"):
|
||||||
|
flag_names = fn._flags
|
||||||
|
else:
|
||||||
|
flag_names = {}
|
||||||
|
|
||||||
|
parsed = docopt(fn.__doc__, args)
|
||||||
|
kwargs = set_flag_vals(flag_names, parsed)
|
||||||
|
colorama.init()
|
||||||
conf.initialize_settings()
|
conf.initialize_settings()
|
||||||
api = LBRYAPIClient.get_client()
|
api = LBRYAPIClient.get_client()
|
||||||
|
|
||||||
|
@ -44,94 +89,43 @@ def main():
|
||||||
print " Status: " + message
|
print " Status: " + message
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
if len(arguments) < 1:
|
|
||||||
print_help(api)
|
|
||||||
return 1
|
|
||||||
|
|
||||||
method = arguments[0]
|
|
||||||
try:
|
|
||||||
params = parse_params(arguments[1:])
|
|
||||||
except InvalidParameters as e:
|
|
||||||
print_error(e.message)
|
|
||||||
return 1
|
|
||||||
|
|
||||||
# TODO: check if port is bound. Error if its not
|
# TODO: check if port is bound. Error if its not
|
||||||
|
|
||||||
if method in ['--help', '-h', 'help']:
|
try:
|
||||||
if len(params) == 0:
|
result = api.call(method, **kwargs)
|
||||||
print_help(api)
|
if isinstance(result, basestring):
|
||||||
elif 'command' not in params:
|
# printing the undumped string is prettier
|
||||||
print_error(
|
print result
|
||||||
'To get help on a specific command, use `{} help command=COMMAND_NAME`'.format(
|
|
||||||
os.path.basename(sys.argv[0]))
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
print_help_for_command(api, params['command'])
|
print utils.json_dumps_pretty(result)
|
||||||
|
except (RPCError, KeyError, JSONRPCException, HTTPError) as err:
|
||||||
|
error_data = None
|
||||||
|
if isinstance(err, HTTPError):
|
||||||
|
error_body = err.read()
|
||||||
|
try:
|
||||||
|
error_data = json.loads(error_body)
|
||||||
|
except ValueError:
|
||||||
|
print (
|
||||||
|
"There was an error, and the response was not valid JSON.\n" +
|
||||||
|
"Raw JSONRPC response:\n" + error_body
|
||||||
|
)
|
||||||
|
return 1
|
||||||
|
|
||||||
elif method not in api.commands():
|
print_error(error_data['error']['message'] + "\n", suggest_help=False)
|
||||||
print_error("'" + method + "' is not a valid command.")
|
else:
|
||||||
|
print_error("Something went wrong\n", suggest_help=False)
|
||||||
|
|
||||||
else:
|
print_help_for_command(method)
|
||||||
try:
|
|
||||||
result = api.call(method, params)
|
|
||||||
if isinstance(result, basestring):
|
|
||||||
# printing the undumped string is prettier
|
|
||||||
print result
|
|
||||||
else:
|
|
||||||
print utils.json_dumps_pretty(result)
|
|
||||||
except (RPCError, KeyError, JSONRPCException, HTTPError) as err:
|
|
||||||
error_data = None
|
|
||||||
if isinstance(err, HTTPError):
|
|
||||||
error_body = err.read()
|
|
||||||
try:
|
|
||||||
error_data = json.loads(error_body)
|
|
||||||
except ValueError:
|
|
||||||
print (
|
|
||||||
"There was an error, and the response was not valid JSON.\n" +
|
|
||||||
"Raw JSONRPC response:\n" + error_body
|
|
||||||
)
|
|
||||||
return 1
|
|
||||||
|
|
||||||
print_error(error_data['error']['message'] + "\n", suggest_help=False)
|
if 'data' in error_data['error'] and 'traceback' in error_data['error']['data']:
|
||||||
else:
|
print "Here's the traceback for the error you encountered:"
|
||||||
print_error("Something went wrong\n", suggest_help=False)
|
print "\n".join(error_data['error']['data']['traceback'])
|
||||||
|
return 1
|
||||||
print_help_for_command(api, method)
|
|
||||||
if 'data' in error_data['error'] and 'traceback' in error_data['error']['data']:
|
|
||||||
print "Here's the traceback for the error you encountered:"
|
|
||||||
print "\n".join(error_data['error']['data']['traceback'])
|
|
||||||
return 1
|
|
||||||
|
|
||||||
|
|
||||||
def parse_params(params):
|
|
||||||
if len(params) > 1:
|
|
||||||
return get_params_from_kwargs(params)
|
|
||||||
elif len(params) == 1:
|
|
||||||
try:
|
|
||||||
return json.loads(params[0])
|
|
||||||
except ValueError:
|
|
||||||
return get_params_from_kwargs(params)
|
|
||||||
else:
|
|
||||||
return {}
|
|
||||||
|
|
||||||
|
|
||||||
class InvalidParameters(Exception):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def get_params_from_kwargs(params):
|
|
||||||
params_for_return = {}
|
|
||||||
for i in params:
|
|
||||||
try:
|
|
||||||
eq_pos = i.index('=')
|
|
||||||
except ValueError:
|
|
||||||
raise InvalidParameters('{} is not in <key>=<value> format'.format(i))
|
|
||||||
k, v = i[:eq_pos], i[eq_pos + 1:]
|
|
||||||
params_for_return[k] = guess_type(v)
|
|
||||||
return params_for_return
|
|
||||||
|
|
||||||
|
|
||||||
def guess_type(x):
|
def guess_type(x):
|
||||||
|
if not isinstance(x, (unicode, str)):
|
||||||
|
return x
|
||||||
if x in ('true', 'True', 'TRUE'):
|
if x in ('true', 'True', 'TRUE'):
|
||||||
return True
|
return True
|
||||||
if x in ('false', 'False', 'FALSE'):
|
if x in ('false', 'False', 'FALSE'):
|
||||||
|
@ -159,7 +153,8 @@ def print_error(message, suggest_help=True):
|
||||||
print_help_suggestion()
|
print_help_suggestion()
|
||||||
|
|
||||||
|
|
||||||
def print_help(api):
|
def print_help():
|
||||||
|
commands = Daemon.callable_methods.keys()
|
||||||
print "\n".join([
|
print "\n".join([
|
||||||
"NAME",
|
"NAME",
|
||||||
" lbrynet-cli - LBRY command line client.",
|
" lbrynet-cli - LBRY command line client.",
|
||||||
|
@ -170,20 +165,18 @@ def print_help(api):
|
||||||
"EXAMPLES",
|
"EXAMPLES",
|
||||||
" lbrynet-cli commands # list available commands",
|
" lbrynet-cli commands # list available commands",
|
||||||
" lbrynet-cli status # get daemon status",
|
" lbrynet-cli status # get daemon status",
|
||||||
" lbrynet-cli resolve_name name=what # resolve a name",
|
" lbrynet-cli resolve_name what # resolve a name",
|
||||||
" lbrynet-cli help command=resolve_name # get help for a command",
|
" lbrynet-cli help resolve_name # get help for a command",
|
||||||
"",
|
"",
|
||||||
"COMMANDS",
|
"COMMANDS",
|
||||||
wrap_list_to_term_width(api.commands(), prefix=' ')
|
wrap_list_to_term_width(commands, prefix=' ')
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
def print_help_for_command(api, command):
|
def print_help_for_command(command):
|
||||||
help_response = api.call('help', {'command': command})
|
fn = Daemon.callable_methods.get(command)
|
||||||
print "Help for %s method:" % command
|
if fn:
|
||||||
message = help_response['help'] if 'help' in help_response else help_response
|
print "Help for %s method:\n%s" % (command, fn.__doc__)
|
||||||
message = "\n".join([' ' + line for line in message.split("\n")])
|
|
||||||
print message
|
|
||||||
|
|
||||||
|
|
||||||
def wrap_list_to_term_width(l, width=None, separator=', ', prefix=''):
|
def wrap_list_to_term_width(l, width=None, separator=', ', prefix=''):
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import logging
|
import logging
|
||||||
import urlparse
|
import urlparse
|
||||||
import inspect
|
|
||||||
import json
|
import json
|
||||||
|
import inspect
|
||||||
|
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
from zope.interface import implements
|
from zope.interface import implements
|
||||||
|
@ -15,9 +15,9 @@ from traceback import format_exc
|
||||||
from lbrynet import conf
|
from lbrynet import conf
|
||||||
from lbrynet.core.Error import InvalidAuthenticationToken
|
from lbrynet.core.Error import InvalidAuthenticationToken
|
||||||
from lbrynet.core import utils
|
from lbrynet.core import utils
|
||||||
from lbrynet.undecorated import undecorated
|
|
||||||
from lbrynet.lbrynet_daemon.auth.util import APIKey, get_auth_message
|
from lbrynet.lbrynet_daemon.auth.util import APIKey, get_auth_message
|
||||||
from lbrynet.lbrynet_daemon.auth.client import LBRY_SECRET
|
from lbrynet.lbrynet_daemon.auth.client import LBRY_SECRET
|
||||||
|
from lbrynet.undecorated import undecorated
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -110,21 +110,30 @@ def jsonrpc_dumps_pretty(obj, **kwargs):
|
||||||
separators=(',', ': '), **kwargs) + "\n"
|
separators=(',', ': '), **kwargs) + "\n"
|
||||||
|
|
||||||
|
|
||||||
class AuthorizedBase(object):
|
class JSONRPCServerType(type):
|
||||||
def __init__(self):
|
def __new__(mcs, name, bases, newattrs):
|
||||||
self.authorized_functions = []
|
klass = type.__new__(mcs, name, bases, newattrs)
|
||||||
self.callable_methods = {}
|
klass.callable_methods = {}
|
||||||
self._call_lock = {}
|
klass.deprecated_methods = {}
|
||||||
self._queued_methods = []
|
klass.authorized_functions = []
|
||||||
|
klass.queued_methods = []
|
||||||
|
|
||||||
for methodname in dir(self):
|
for methodname in dir(klass):
|
||||||
if methodname.startswith("jsonrpc_"):
|
if methodname.startswith("jsonrpc_"):
|
||||||
method = getattr(self, methodname)
|
method = getattr(klass, methodname)
|
||||||
self.callable_methods.update({methodname.split("jsonrpc_")[1]: method})
|
if not hasattr(method, '_deprecated'):
|
||||||
if hasattr(method, '_auth_required'):
|
klass.callable_methods.update({methodname.split("jsonrpc_")[1]: method})
|
||||||
self.authorized_functions.append(methodname.split("jsonrpc_")[1])
|
if hasattr(method, '_auth_required'):
|
||||||
if hasattr(method, '_queued'):
|
klass.authorized_functions.append(methodname.split("jsonrpc_")[1])
|
||||||
self._queued_methods.append(methodname.split("jsonrpc_")[1])
|
if hasattr(method, '_queued'):
|
||||||
|
klass.queued_methods.append(methodname.split("jsonrpc_")[1])
|
||||||
|
else:
|
||||||
|
klass.deprecated_methods.update({methodname.split("jsonrpc_")[1]: method})
|
||||||
|
return klass
|
||||||
|
|
||||||
|
|
||||||
|
class AuthorizedBase(object):
|
||||||
|
__metaclass__ = JSONRPCServerType
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def auth_required(f):
|
def auth_required(f):
|
||||||
|
@ -136,6 +145,23 @@ class AuthorizedBase(object):
|
||||||
f._queued = True
|
f._queued = True
|
||||||
return f
|
return f
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def deprecated(new_command=None):
|
||||||
|
def _deprecated_wrapper(f):
|
||||||
|
f._new_command = new_command
|
||||||
|
f._deprecated = True
|
||||||
|
return f
|
||||||
|
return _deprecated_wrapper
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def flags(**kwargs):
|
||||||
|
def _flag_wrapper(f):
|
||||||
|
f._flags = {}
|
||||||
|
for k, v in kwargs.iteritems():
|
||||||
|
f._flags[v] = k
|
||||||
|
return f
|
||||||
|
return _flag_wrapper
|
||||||
|
|
||||||
|
|
||||||
class AuthJSONRPCServer(AuthorizedBase):
|
class AuthJSONRPCServer(AuthorizedBase):
|
||||||
"""Authorized JSONRPC server used as the base class for the LBRY API
|
"""Authorized JSONRPC server used as the base class for the LBRY API
|
||||||
|
@ -164,7 +190,7 @@ class AuthJSONRPCServer(AuthorizedBase):
|
||||||
isLeaf = True
|
isLeaf = True
|
||||||
|
|
||||||
def __init__(self, use_authentication=None):
|
def __init__(self, use_authentication=None):
|
||||||
AuthorizedBase.__init__(self)
|
self._call_lock = {}
|
||||||
self._use_authentication = (
|
self._use_authentication = (
|
||||||
use_authentication if use_authentication is not None else conf.settings['use_auth_http']
|
use_authentication if use_authentication is not None else conf.settings['use_auth_http']
|
||||||
)
|
)
|
||||||
|
@ -263,7 +289,7 @@ class AuthJSONRPCServer(AuthorizedBase):
|
||||||
id_ = None
|
id_ = None
|
||||||
try:
|
try:
|
||||||
function_name = parsed.get('method')
|
function_name = parsed.get('method')
|
||||||
is_queued = function_name in self._queued_methods
|
is_queued = function_name in self.queued_methods
|
||||||
args = parsed.get('params', {})
|
args = parsed.get('params', {})
|
||||||
id_ = parsed.get('id', None)
|
id_ = parsed.get('id', None)
|
||||||
token = parsed.pop('hmac', None)
|
token = parsed.pop('hmac', None)
|
||||||
|
@ -312,12 +338,16 @@ class AuthJSONRPCServer(AuthorizedBase):
|
||||||
|
|
||||||
if args == EMPTY_PARAMS or args == []:
|
if args == EMPTY_PARAMS or args == []:
|
||||||
args_dict = {}
|
args_dict = {}
|
||||||
|
_args, _kwargs = (), {}
|
||||||
elif isinstance(args, dict):
|
elif isinstance(args, dict):
|
||||||
args_dict = args
|
args_dict = args
|
||||||
elif len(args) == 1 and isinstance(args[0], dict):
|
elif len(args) == 1 and isinstance(args[0], dict):
|
||||||
# TODO: this is for backwards compatibility. Remove this once API and UI are updated
|
# TODO: this is for backwards compatibility. Remove this once API and UI are updated
|
||||||
# TODO: also delete EMPTY_PARAMS then
|
# TODO: also delete EMPTY_PARAMS then
|
||||||
args_dict = args[0]
|
args_dict = args[0]
|
||||||
|
_args, _kwargs = (), args
|
||||||
|
elif isinstance(args, list):
|
||||||
|
_args, _kwargs = args, {}
|
||||||
else:
|
else:
|
||||||
# d = defer.maybeDeferred(function, *args) # if we want to support positional args too
|
# d = defer.maybeDeferred(function, *args) # if we want to support positional args too
|
||||||
raise ValueError('Args must be a dict')
|
raise ValueError('Args must be a dict')
|
||||||
|
@ -337,7 +367,7 @@ class AuthJSONRPCServer(AuthorizedBase):
|
||||||
if is_queued:
|
if is_queued:
|
||||||
d_lock = self._call_lock.get(function_name, False)
|
d_lock = self._call_lock.get(function_name, False)
|
||||||
if not d_lock:
|
if not d_lock:
|
||||||
d = defer.maybeDeferred(function, **args_dict)
|
d = defer.maybeDeferred(function, self, **args_dict)
|
||||||
self._call_lock[function_name] = finished_deferred
|
self._call_lock[function_name] = finished_deferred
|
||||||
|
|
||||||
def _del_lock(*args):
|
def _del_lock(*args):
|
||||||
|
@ -352,9 +382,9 @@ class AuthJSONRPCServer(AuthorizedBase):
|
||||||
log.info("queued %s", function_name)
|
log.info("queued %s", function_name)
|
||||||
d = d_lock
|
d = d_lock
|
||||||
d.addBoth(lambda _: log.info("running %s from queue", function_name))
|
d.addBoth(lambda _: log.info("running %s from queue", function_name))
|
||||||
d.addCallback(lambda _: defer.maybeDeferred(function, **args_dict))
|
d.addCallback(lambda _: defer.maybeDeferred(function, self, **args_dict))
|
||||||
else:
|
else:
|
||||||
d = defer.maybeDeferred(function, **args_dict)
|
d = defer.maybeDeferred(function, self, **args_dict)
|
||||||
|
|
||||||
# finished_deferred will callback when the request is finished
|
# finished_deferred will callback when the request is finished
|
||||||
# and errback if something went wrong. If the errback is
|
# and errback if something went wrong. If the errback is
|
||||||
|
@ -374,28 +404,6 @@ class AuthJSONRPCServer(AuthorizedBase):
|
||||||
(utils.now() - time_in).total_seconds()))
|
(utils.now() - time_in).total_seconds()))
|
||||||
return server.NOT_DONE_YET
|
return server.NOT_DONE_YET
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _check_params(function, args_dict):
|
|
||||||
argspec = inspect.getargspec(undecorated(function))
|
|
||||||
num_optional_params = 0 if argspec.defaults is None else len(argspec.defaults)
|
|
||||||
missing_required_params = [
|
|
||||||
required_param
|
|
||||||
for required_param in argspec.args[1:-num_optional_params]
|
|
||||||
if required_param not in args_dict
|
|
||||||
]
|
|
||||||
if len(missing_required_params):
|
|
||||||
return 'Missing required parameters', missing_required_params
|
|
||||||
|
|
||||||
extraneous_params = [] if argspec.keywords is not None else [
|
|
||||||
extra_param
|
|
||||||
for extra_param in args_dict
|
|
||||||
if extra_param not in argspec.args[1:]
|
|
||||||
]
|
|
||||||
if len(extraneous_params):
|
|
||||||
return 'Extraneous parameters', extraneous_params
|
|
||||||
|
|
||||||
return None, None
|
|
||||||
|
|
||||||
def _register_user_session(self, session_id):
|
def _register_user_session(self, session_id):
|
||||||
"""
|
"""
|
||||||
Add or update a HMAC secret for a session
|
Add or update a HMAC secret for a session
|
||||||
|
@ -454,6 +462,16 @@ class AuthJSONRPCServer(AuthorizedBase):
|
||||||
else:
|
else:
|
||||||
return server_port[0], 80
|
return server_port[0], 80
|
||||||
|
|
||||||
|
def _check_deprecated(self, function_path):
|
||||||
|
if function_path in self.deprecated_methods:
|
||||||
|
deprecated_fn = self.deprecated_methods[function_path]
|
||||||
|
deprecated_function_path = function_path
|
||||||
|
new_function_path = deprecated_fn._new_command
|
||||||
|
log.warning("\"%s\" is deprecated, please update to use \"%s\"",
|
||||||
|
deprecated_function_path, new_function_path)
|
||||||
|
return new_function_path
|
||||||
|
return function_path
|
||||||
|
|
||||||
def _verify_method_is_callable(self, function_path):
|
def _verify_method_is_callable(self, function_path):
|
||||||
if function_path not in self.callable_methods:
|
if function_path not in self.callable_methods:
|
||||||
raise UnknownAPIMethodError(function_path)
|
raise UnknownAPIMethodError(function_path)
|
||||||
|
@ -462,9 +480,32 @@ class AuthJSONRPCServer(AuthorizedBase):
|
||||||
raise NotAllowedDuringStartupError(function_path)
|
raise NotAllowedDuringStartupError(function_path)
|
||||||
|
|
||||||
def _get_jsonrpc_method(self, function_path):
|
def _get_jsonrpc_method(self, function_path):
|
||||||
|
function_path = self._check_deprecated(function_path)
|
||||||
self._verify_method_is_callable(function_path)
|
self._verify_method_is_callable(function_path)
|
||||||
return self.callable_methods.get(function_path)
|
return self.callable_methods.get(function_path)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _check_params(function, args_dict):
|
||||||
|
argspec = inspect.getargspec(undecorated(function))
|
||||||
|
num_optional_params = 0 if argspec.defaults is None else len(argspec.defaults)
|
||||||
|
missing_required_params = [
|
||||||
|
required_param
|
||||||
|
for required_param in argspec.args[1:-num_optional_params]
|
||||||
|
if required_param not in args_dict
|
||||||
|
]
|
||||||
|
if len(missing_required_params):
|
||||||
|
return 'Missing required parameters', missing_required_params
|
||||||
|
|
||||||
|
extraneous_params = [] if argspec.keywords is not None else [
|
||||||
|
extra_param
|
||||||
|
for extra_param in args_dict
|
||||||
|
if extra_param not in argspec.args[1:]
|
||||||
|
]
|
||||||
|
if len(extraneous_params):
|
||||||
|
return 'Extraneous parameters', extraneous_params
|
||||||
|
|
||||||
|
return None, None
|
||||||
|
|
||||||
def _initialize_session(self, session_id):
|
def _initialize_session(self, session_id):
|
||||||
if not self.sessions.get(session_id, False):
|
if not self.sessions.get(session_id, False):
|
||||||
self._register_user_session(session_id)
|
self._register_user_session(session_id)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
Twisted==16.6.0
|
Twisted==16.6.0
|
||||||
appdirs==1.4.3
|
appdirs==1.4.3
|
||||||
argparse==1.2.1
|
argparse==1.2.1
|
||||||
|
docopt==0.6.2
|
||||||
base58==0.2.2
|
base58==0.2.2
|
||||||
git+https://github.com/lbryio/bumpversion.git#egg=bumpversion
|
git+https://github.com/lbryio/bumpversion.git#egg=bumpversion
|
||||||
colorama==0.3.7
|
colorama==0.3.7
|
||||||
|
|
1
setup.py
1
setup.py
|
@ -31,6 +31,7 @@ requires = [
|
||||||
'seccure',
|
'seccure',
|
||||||
'txJSON-RPC',
|
'txJSON-RPC',
|
||||||
'zope.interface',
|
'zope.interface',
|
||||||
|
'docopt'
|
||||||
]
|
]
|
||||||
|
|
||||||
console_scripts = [
|
console_scripts = [
|
||||||
|
|
102
tests/integration/test_integration.py
Normal file
102
tests/integration/test_integration.py
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
"""
|
||||||
|
Start up the actual daemon and test some non blockchain commands here
|
||||||
|
"""
|
||||||
|
|
||||||
|
from jsonrpc.proxy import JSONRPCProxy
|
||||||
|
import json
|
||||||
|
import subprocess
|
||||||
|
import unittest
|
||||||
|
import time
|
||||||
|
import os
|
||||||
|
|
||||||
|
from urllib2 import URLError
|
||||||
|
from httplib import BadStatusLine
|
||||||
|
from socket import error
|
||||||
|
|
||||||
|
|
||||||
|
def shell_command(command):
|
||||||
|
FNULL = open(os.devnull, 'w')
|
||||||
|
p = subprocess.Popen(command,shell=False,stdout=FNULL,stderr=subprocess.STDOUT)
|
||||||
|
|
||||||
|
def lbrynet_cli(commands):
|
||||||
|
cli_cmd=['lbrynet-cli']
|
||||||
|
for cmd in commands:
|
||||||
|
cli_cmd.append(cmd)
|
||||||
|
p = subprocess.Popen(cli_cmd,shell=False,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
|
||||||
|
out,err = p.communicate()
|
||||||
|
return out,err
|
||||||
|
|
||||||
|
lbrynet_rpc_port = '5279'
|
||||||
|
lbrynet = JSONRPCProxy.from_url("http://localhost:{}/lbryapi".format(lbrynet_rpc_port))
|
||||||
|
|
||||||
|
|
||||||
|
class TestIntegration(unittest.TestCase):
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
shell_command(['lbrynet-daemon'])
|
||||||
|
start_time = time.time()
|
||||||
|
STARTUP_TIMEOUT = 180
|
||||||
|
while time.time() - start_time < STARTUP_TIMEOUT:
|
||||||
|
try:
|
||||||
|
status = lbrynet.status()
|
||||||
|
except (URLError,error,BadStatusLine) as e:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
if status['is_running'] == True:
|
||||||
|
return
|
||||||
|
time.sleep(1)
|
||||||
|
raise Exception('lbrynet daemon failed to start')
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def tearDownClass(cls):
|
||||||
|
shell_command(['lbrynet-cli', 'daemon_stop'])
|
||||||
|
|
||||||
|
def test_cli(self):
|
||||||
|
help_out,err = lbrynet_cli(['help'])
|
||||||
|
self.assertTrue(help_out)
|
||||||
|
|
||||||
|
out,err = lbrynet_cli(['-h'])
|
||||||
|
self.assertEqual(out, help_out)
|
||||||
|
|
||||||
|
out,err = lbrynet_cli(['--help'])
|
||||||
|
self.assertEqual(out, help_out)
|
||||||
|
|
||||||
|
out,err = lbrynet_cli(['status'])
|
||||||
|
out = json.loads(out)
|
||||||
|
self.assertTrue(out['is_running'])
|
||||||
|
|
||||||
|
|
||||||
|
def test_cli_docopts(self):
|
||||||
|
out,err = lbrynet_cli(['cli_test_command'])
|
||||||
|
self.assertEqual('',out)
|
||||||
|
self.assertTrue('Usage' in err)
|
||||||
|
|
||||||
|
out,err = lbrynet_cli(['cli_test_command','1','--not_a_arg=1'])
|
||||||
|
self.assertEqual('',out)
|
||||||
|
self.assertTrue('Usage' in err)
|
||||||
|
|
||||||
|
out,err = lbrynet_cli(['cli_test_command','1'])
|
||||||
|
out = json.loads(out)
|
||||||
|
self.assertEqual([1,[],None,None], out)
|
||||||
|
|
||||||
|
out,err = lbrynet_cli(['cli_test_command','1','--pos_arg2=1'])
|
||||||
|
out = json.loads(out)
|
||||||
|
self.assertEqual([1,[],1,None], out)
|
||||||
|
|
||||||
|
|
||||||
|
out,err = lbrynet_cli(['cli_test_command','1', '--pos_arg2=2','--pos_arg3=3'])
|
||||||
|
out = json.loads(out)
|
||||||
|
self.assertEqual([1,[],2,3], out)
|
||||||
|
|
||||||
|
out,err = lbrynet_cli(['cli_test_command','1','2','3'])
|
||||||
|
out = json.loads(out)
|
||||||
|
# TODO: variable length arguments don't have guess_type() on them
|
||||||
|
self.assertEqual([1,['2','3'],None,None], out)
|
||||||
|
|
||||||
|
|
||||||
|
def test_status(self):
|
||||||
|
out = lbrynet.status()
|
||||||
|
self.assertTrue(out['is_running'])
|
||||||
|
|
||||||
|
if __name__ =='__main__':
|
||||||
|
unittest.main()
|
|
@ -16,23 +16,3 @@ class DaemonCLITests(unittest.TestCase):
|
||||||
self.assertEqual(False, DaemonCLI.guess_type('false'))
|
self.assertEqual(False, DaemonCLI.guess_type('false'))
|
||||||
self.assertEqual(False, DaemonCLI.guess_type('False'))
|
self.assertEqual(False, DaemonCLI.guess_type('False'))
|
||||||
|
|
||||||
def test_get_params(self):
|
|
||||||
test_params = [
|
|
||||||
'b64address=VdNmakxFORPSyfCprAD/eDDPk5TY9QYtSA==',
|
|
||||||
'name=test',
|
|
||||||
'amount=5.3',
|
|
||||||
'n=5',
|
|
||||||
'address=bY13xeAjLrsjP4KGETwStK2a9UgKgXVTXu',
|
|
||||||
't=true',
|
|
||||||
'f=False',
|
|
||||||
]
|
|
||||||
test_r = {
|
|
||||||
'b64address': 'VdNmakxFORPSyfCprAD/eDDPk5TY9QYtSA==',
|
|
||||||
'name': 'test',
|
|
||||||
'amount': 5.3,
|
|
||||||
'n': 5,
|
|
||||||
'address': 'bY13xeAjLrsjP4KGETwStK2a9UgKgXVTXu',
|
|
||||||
't': True,
|
|
||||||
'f': False,
|
|
||||||
}
|
|
||||||
self.assertDictEqual(test_r, DaemonCLI.get_params_from_kwargs(test_params))
|
|
||||||
|
|
Loading…
Reference in a new issue