Skip to content

Commit

Permalink
[UPD] Add and update docstrings
Browse files Browse the repository at this point in the history
  • Loading branch information
mccwdev committed Dec 1, 2020
1 parent 999e553 commit d8aa477
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 89 deletions.
2 changes: 1 addition & 1 deletion bitcoinlib/networks.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ def wif_prefix_search(wif, witness_type=None, multisig=None, network=None):
return matches


# Replace by Value class
# Replaced by Value class
@deprecated
def print_value(value, network=DEFAULT_NETWORK, rep='string', denominator=1, decimals=None):
"""
Expand Down
1 change: 1 addition & 0 deletions bitcoinlib/transactions.py
Original file line number Diff line number Diff line change
Expand Up @@ -1734,6 +1734,7 @@ def sign(self, keys=None, tid=None, multisig_key_n=None, hash_type=SIGHASH_ALL,
if _fail_on_unknown_key:
raise TransactionError("This key does not sign any known key: %s" % key.public_hex)
else:
_logger.info("This key does not sign any known key: %s" % key.public_hex)
continue
if key in [x.public_key for x in self.inputs[tid].signatures]:
_logger.info("Key %s already signed" % key.public_hex)
Expand Down
189 changes: 109 additions & 80 deletions bitcoinlib/values.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,85 +184,6 @@ def __repr__(self):
return "Value(value=%.14f, denominator=%.8f, network='%s')" % \
(self.value, self.denominator, self.network.name)

def str(self, denominator=None, decimals=None, currency_repr='code'):
"""
Get string representation of Value with requested denominator and number of decimals.
>>> Value(1200000, 'sat').str('m') # milli Bitcoin
'12.00000 mBTC'
>>> Value(12000.3, 'sat').str(1) # Use denominator = 1 for Bitcoin
'0.00012000 BTC'
>>> Value(12000, 'sat').str('auto')
'120.00 µBTC'
>>> Value(0.005).str('m')
'5.00000 mBTC'
>>> Value(12000, 'sat').str('auto', decimals=0)
'120 µBTC'
>>> Value('13000000 Doge').str('auto') # Yeah, mega Dogecoins...
'13.00000000 MDOGE'
>>> Value('2100000000').str('auto')
'2.10000000 GBTC'
:param denominator: Denominator as integer or string. Such as 0.001 or m for milli, 1000 or k for kilo, etc. See NETWORK_DENOMINATORS for list of available denominator symbols. If not provided the default self.denominator value is used. Use value 'auto' to automatically determine best denominator for human readability.
:type denominator: int, float, str
:param decimals: Number of decimals to use
:type decimals: float
:return str:
"""
if denominator is None:
denominator = self.denominator
elif denominator == 'auto':
# First try denominator=1 and smallest denominator (satoshi)
if 0.001 <= self.value < 1000:
denominator = 1
elif 1 <= self.value / self.network.denominator < 1000:
denominator = self.network.denominator
else: # Try other frequently used denominators
for den, symb in NETWORK_DENOMINATORS.items():
if symb in ['n', 'fin', 'da', 'c', 'd', 'h']:
continue
if 1 <= self.value / den < 1000:
denominator = den
elif isinstance(denominator, str):
dens = [den for den, symb in NETWORK_DENOMINATORS.items() if symb == denominator[:len(symb)] and len(symb)]
if len(dens) > 1:
dens = [den for den, symb in NETWORK_DENOMINATORS.items() if symb == denominator]
if dens:
denominator = dens[0]
if denominator in NETWORK_DENOMINATORS:
den_symb = NETWORK_DENOMINATORS[denominator]
else:
raise ValueError("Denominator not found in NETWORK_DENOMINATORS definition")

if decimals is None:
decimals = -int(math.log10(self.network.denominator / denominator))
if decimals > 8:
decimals = 8
if decimals < 0:
decimals = 0
balance = round(self.value / denominator, decimals)
cur_code = self.network.currency_code
if currency_repr == 'symbol':
cur_code = self.network.currency_symbol
if currency_repr == 'name':
cur_code = self.network.currency_name_plural
if 'sat' in den_symb and self.network.name == 'bitcoin':
cur_code = ''
return ("%%.%df %%s%%s" % decimals) % (balance, den_symb, cur_code)

def str1(self, decimals=None, currency_repr='code'):
return self.str(1, decimals, currency_repr)

def str_auto(self, decimals=None, currency_repr='code'):
return self.str('auto', decimals, currency_repr)

def __int__(self):
return int(self.value)

Expand Down Expand Up @@ -348,6 +269,115 @@ def __round__(self, n=0):
def __index__(self):
return self.value_sat

def str(self, denominator=None, decimals=None, currency_repr='code'):
"""
Get string representation of Value with requested denominator and number of decimals.
>>> Value(1200000, 'sat').str('m') # milli Bitcoin
'12.00000 mBTC'
>>> Value(12000.3, 'sat').str(1) # Use denominator = 1 for Bitcoin
'0.00012000 BTC'
>>> Value(12000, 'sat').str('auto')
'120.00 µBTC'
>>> Value(0.005).str('m')
'5.00000 mBTC'
>>> Value(12000, 'sat').str('auto', decimals=0)
'120 µBTC'
>>> Value('13000000 Doge').str('auto') # Yeah, mega Dogecoins...
'13.00000000 MDOGE'
>>> Value('2100000000').str('auto')
'2.10000000 GBTC'
:param denominator: Denominator as integer or string. Such as 0.001 or m for milli, 1000 or k for kilo, etc. See NETWORK_DENOMINATORS for list of available denominator symbols. If not provided the default self.denominator value is used. Use value 'auto' to automatically determine best denominator for human readability.
:type denominator: int, float, str
:param decimals: Number of decimals to use
:type decimals: float
:param currency_repr: Representation of currency. I.e. code: BTC, name: Bitcoin, symbol: ฿
:type currency_repr: str
:return str:
"""
if denominator is None:
denominator = self.denominator
elif denominator == 'auto':
# First try denominator=1 and smallest denominator (satoshi)
if 0.001 <= self.value < 1000:
denominator = 1
elif 1 <= self.value / self.network.denominator < 1000:
denominator = self.network.denominator
else: # Try other frequently used denominators
for den, symb in NETWORK_DENOMINATORS.items():
if symb in ['n', 'fin', 'da', 'c', 'd', 'h']:
continue
if 1 <= self.value / den < 1000:
denominator = den
elif isinstance(denominator, str):
dens = [den for den, symb in NETWORK_DENOMINATORS.items() if symb == denominator[:len(symb)] and len(symb)]
if len(dens) > 1:
dens = [den for den, symb in NETWORK_DENOMINATORS.items() if symb == denominator]
if dens:
denominator = dens[0]
if denominator in NETWORK_DENOMINATORS:
den_symb = NETWORK_DENOMINATORS[denominator]
else:
raise ValueError("Denominator not found in NETWORK_DENOMINATORS definition")

if decimals is None:
decimals = -int(math.log10(self.network.denominator / denominator))
if decimals > 8:
decimals = 8
if decimals < 0:
decimals = 0
balance = round(self.value / denominator, decimals)
cur_code = self.network.currency_code
if currency_repr == 'symbol':
cur_code = self.network.currency_symbol
if currency_repr == 'name':
cur_code = self.network.currency_name_plural
if 'sat' in den_symb and self.network.name == 'bitcoin':
cur_code = ''
return ("%%.%df %%s%%s" % decimals) % (balance, den_symb, cur_code)

def str_unit(self, decimals=None, currency_repr='code'):
"""
String representation of this Value. Wrapper for the str() method, but always uses 1 as denominator, meaning main denominator such as BTC, LTC.
>>> Value('12000 sat').str_unit()
'0.00012000 BTC'
:param decimals: Number of decimals to use
:type decimals: float
:param currency_repr: Representation of currency. I.e. code: BTC, name: Bitcoin, symbol: ฿
:type currency_repr: str
:return str:
"""
return self.str(1, decimals, currency_repr)

def str_auto(self, decimals=None, currency_repr='code'):
"""
String representation of this Value. Wrapper for the str() method, but automatically determines the denominator depending on the value.
>>> Value('0.0000012 BTC').str_auto()
'120 sat'
>>> Value('0.0005 BTC').str_auto()
'500.00 µBTC'
:param decimals: Number of decimals to use
:type decimals: float
:param currency_repr: Representation of currency. I.e. code: BTC, name: Bitcoin, symbol: ฿
:type currency_repr: str
:return str:
"""

return self.str('auto', decimals, currency_repr)

@property
def value_sat(self):
"""
Expand Down Expand Up @@ -387,4 +417,3 @@ def to_hex(self, length=16, byteorder='little'):
:return:
"""
return self.value_sat.to_bytes(length // 2, byteorder).hex()

16 changes: 8 additions & 8 deletions bitcoinlib/wallets.py
Original file line number Diff line number Diff line change
Expand Up @@ -514,7 +514,7 @@ def balance(self, as_string=False):
"""

if as_string:
return Value.from_satoshi(self._balance, network=self.network).str1()
return Value.from_satoshi(self._balance, network=self.network).str_unit()
else:
return self._balance

Expand Down Expand Up @@ -713,7 +713,7 @@ def sign(self, keys=None, index_n=0, multisig_key_n=None, hash_type=SIGHASH_ALL,
for priv_key in keys:
if not isinstance(priv_key, HDKey):
if isinstance(priv_key, str) and len(str(priv_key).split(' ')) > 4:
priv_key = HDKey.from_passphrase(priv_key)
priv_key = HDKey.from_passphrase(priv_key, network=self.network)
else:
priv_key = HDKey(priv_key, network=self.network.name)
priv_key_list_arg.append((None, priv_key))
Expand All @@ -737,7 +737,7 @@ def send(self, offline=False):
Verify and push transaction to network. Update UTXO's in database after successful send
:param offline: Just return the transaction object and do not send it when offline = True. Default is False
:type offline: boolmijn ouders relatief normaal waren. Je hebt ze tenslotte niet voor het uitzoeken
:type offline: bool
:return None:
Expand Down Expand Up @@ -2511,7 +2511,7 @@ def balance(self, account_id=None, network=None, as_string=False):
if len(b_res):
balance = b_res[0]
if as_string:
return Value.from_satoshi(balance, network=network).str1()
return Value.from_satoshi(balance, network=network).str_unit()
else:
return float(balance)

Expand Down Expand Up @@ -3920,7 +3920,7 @@ def info(self, detail=3):
for key in self.keys(depth=d, network=nw.name, is_active=is_active):
print("%5s %-28s %-45s %-25s %25s" %
(key.id, key.path, key.address, key.name,
Value.from_satoshi(key.balance, network=nw).str1(currency_repr='symbol')))
Value.from_satoshi(key.balance, network=nw).str_unit(currency_repr='symbol')))

if detail > 2:
include_new = False
Expand All @@ -3944,14 +3944,14 @@ def info(self, detail=3):
if tx['status'] not in ['confirmed', 'unconfirmed']:
status = tx['status']
print("%64s %43s %8d %21s %s %s" % (tx['txid'], address, tx['confirmations'],
Value.from_satoshi(tx['value'], network=nw).str1(
Value.from_satoshi(tx['value'], network=nw).str_unit(
currency_repr='symbol'),
spent, status))
print("\n= Balance Totals (includes unconfirmed) =")
for na_balance in balances:
print("%-20s %-20s %20s" % (na_balance['network'], "(Account %s)" % na_balance['account_id'],
Value.from_satoshi(na_balance['balance'], network=na_balance['network']).str1(
currency_repr='symbol')))
Value.from_satoshi(na_balance['balance'], network=na_balance['network']).
str_unit(currency_repr='symbol')))
print("\n")

def as_dict(self, include_private=False):
Expand Down

0 comments on commit d8aa477

Please sign in to comment.