py3
This commit is contained in:
245
lib/util.py
245
lib/util.py
@@ -22,7 +22,12 @@
|
||||
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import binascii
|
||||
import os, sys, re, json
|
||||
import platform
|
||||
import shutil
|
||||
@@ -30,10 +35,18 @@ from collections import defaultdict
|
||||
from datetime import datetime
|
||||
from decimal import Decimal
|
||||
import traceback
|
||||
import urlparse
|
||||
import urllib
|
||||
import threading
|
||||
from i18n import _
|
||||
from .i18n import _
|
||||
|
||||
import six
|
||||
from six.moves import queue, urllib_parse
|
||||
|
||||
try:
|
||||
import urllib.parse
|
||||
import urllib.request, urllib.parse, urllib.error
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
base_units = {'BTC':8, 'mBTC':5, 'uBTC':2}
|
||||
fee_levels = [_('Within 25 blocks'), _('Within 10 blocks'), _('Within 5 blocks'), _('Within 2 blocks'), _('In the next block')]
|
||||
@@ -194,7 +207,7 @@ def json_decode(x):
|
||||
# decorator that prints execution time
|
||||
def profiler(func):
|
||||
def do_profile(func, args, kw_args):
|
||||
n = func.func_name
|
||||
n = func.__name__
|
||||
t0 = time.time()
|
||||
o = func(*args, **kw_args)
|
||||
t = time.time() - t0
|
||||
@@ -238,6 +251,182 @@ def android_check_data_dir():
|
||||
def get_headers_dir(config):
|
||||
return android_headers_dir() if 'ANDROID_DATA' in os.environ else config.path
|
||||
|
||||
|
||||
def assert_bytes(*args):
|
||||
"""
|
||||
porting helper, assert args type
|
||||
"""
|
||||
if six.PY2:
|
||||
for x in args:
|
||||
assert isinstance(x, (bytes, bytearray, str))
|
||||
return
|
||||
|
||||
try:
|
||||
if six.PY3:
|
||||
for x in args:
|
||||
assert isinstance(x, (bytes, bytearray))
|
||||
else:
|
||||
for x in args:
|
||||
assert isinstance(x, bytearray)
|
||||
except:
|
||||
print('assert bytes failed', list(map(type, args)))
|
||||
raise
|
||||
|
||||
|
||||
def assert_str(*args):
|
||||
"""
|
||||
porting helper, assert args type
|
||||
"""
|
||||
for x in args:
|
||||
assert isinstance(x, six.string_types)
|
||||
|
||||
|
||||
def __str(x, encoding='utf8'):
|
||||
if six.PY3:
|
||||
return x.decode(encoding)
|
||||
|
||||
|
||||
def _bytes(x=None, encoding=None, **kw):
|
||||
"""
|
||||
py2-py3 aware wrapper to "bytes()" like constructor
|
||||
:param x:
|
||||
:return:
|
||||
"""
|
||||
if encoding is not None:
|
||||
kw['encoding'] = encoding
|
||||
if x is None:
|
||||
x = []
|
||||
if six.PY3:
|
||||
if isinstance(x, bytes):
|
||||
return x
|
||||
return bytes(x, **kw)
|
||||
else:
|
||||
return bytearray(x, **kw)
|
||||
|
||||
|
||||
def _to_bytes2(x, enc):
|
||||
if isinstance(x, bytearray):
|
||||
return bytearray(x)
|
||||
if isinstance(x, six.text_type):
|
||||
return bytearray(x.encode(enc))
|
||||
elif isinstance(x, six.binary_type):
|
||||
return bytearray(x)
|
||||
else:
|
||||
raise TypeError("Not a string or bytes like object")
|
||||
|
||||
|
||||
def _to_bytes3(x, enc):
|
||||
if isinstance(x, bytes):
|
||||
return x
|
||||
if isinstance(x, str):
|
||||
return x.encode(enc)
|
||||
elif isinstance(x, bytearray):
|
||||
return bytes(x)
|
||||
else:
|
||||
raise TypeError("Not a string or bytes like object")
|
||||
|
||||
|
||||
def _to_string2(x, enc):
|
||||
if isinstance(x, (str, bytes)):
|
||||
return x
|
||||
if isinstance(x, unicode):
|
||||
return x.encode(enc)
|
||||
if isinstance(x, bytearray):
|
||||
return x.decode(enc)
|
||||
else:
|
||||
raise TypeError("Not a string or bytes like object")
|
||||
|
||||
|
||||
def _to_string3(x, enc):
|
||||
if isinstance(x, (bytes, bytearray)):
|
||||
return x.decode(enc)
|
||||
if isinstance(x, str):
|
||||
return x
|
||||
else:
|
||||
raise TypeError("Not a string or bytes like object")
|
||||
|
||||
def to_bytes(something, encoding='utf8'):
|
||||
"""
|
||||
cast string to bytes() like object, but for python2 support it's bytearray copy
|
||||
"""
|
||||
raise NotImplementedError("This call should be redefined")
|
||||
|
||||
def to_bytes(something, encoding='utf8'):
|
||||
"""
|
||||
cast string to str object
|
||||
"""
|
||||
raise NotImplementedError("This call should be redefined")
|
||||
|
||||
if six.PY3:
|
||||
to_bytes = _to_bytes3
|
||||
to_string = _to_string3
|
||||
else:
|
||||
to_bytes = _to_bytes2
|
||||
to_string = _to_string2
|
||||
|
||||
if six.PY3:
|
||||
bfh_builder = lambda x: bytes.fromhex(x)
|
||||
else:
|
||||
bfh_builder = lambda x: x.decode('hex') # str(bytearray.fromhex(x))
|
||||
|
||||
|
||||
# def ufh(x):
|
||||
# """
|
||||
# py2-py3 aware wrapper for str.decode('hex')
|
||||
# :param x: str
|
||||
# :return: str
|
||||
# """
|
||||
# if
|
||||
# return binascii.unhexlify(x)
|
||||
|
||||
|
||||
def hfu(x):
|
||||
"""
|
||||
py2-py3 aware wrapper for str.encode('hex')
|
||||
:param x: str
|
||||
:return: str
|
||||
"""
|
||||
if six.PY3:
|
||||
assert_bytes(x)
|
||||
return binascii.hexlify(x)
|
||||
else:
|
||||
return x.encode('hex')
|
||||
|
||||
|
||||
def bfh(x):
|
||||
"""
|
||||
py2-py3 aware wrapper to "bytes.fromhex()" func
|
||||
:param x: str
|
||||
:rtype: bytes
|
||||
"""
|
||||
if isinstance(x, six.string_types):
|
||||
return bfh_builder(x)
|
||||
# TODO: check for iterator interface
|
||||
elif isinstance(x, (list, tuple, map)):
|
||||
return [bfh(sub) for sub in x]
|
||||
else:
|
||||
raise TypeError('Unexpected type: ' + type(x))
|
||||
|
||||
|
||||
def bh2u(x):
|
||||
"""
|
||||
unicode with hex representation of bytes()
|
||||
e.g. x = bytes([1, 2, 10])
|
||||
bh2u(x) -> '01020A'
|
||||
:param x: bytes
|
||||
:rtype: str
|
||||
"""
|
||||
if six.PY3:
|
||||
assert_bytes(x)
|
||||
# x = to_bytes(x, 'ascii')
|
||||
return binascii.hexlify(x).decode('ascii')
|
||||
else:
|
||||
if isinstance(x, bytearray):
|
||||
return binascii.hexlify(x)
|
||||
else:
|
||||
return x.encode('hex')
|
||||
|
||||
|
||||
def user_dir():
|
||||
if 'ANDROID_DATA' in os.environ:
|
||||
return android_check_data_dir()
|
||||
@@ -251,12 +440,14 @@ def user_dir():
|
||||
#raise Exception("No home directory found in environment variables.")
|
||||
return
|
||||
|
||||
|
||||
def format_satoshis_plain(x, decimal_point = 8):
|
||||
'''Display a satoshi amount scaled. Always uses a '.' as a decimal
|
||||
point and has no thousands separator'''
|
||||
"""Display a satoshi amount scaled. Always uses a '.' as a decimal
|
||||
point and has no thousands separator"""
|
||||
scale_factor = pow(10, decimal_point)
|
||||
return "{:.8f}".format(Decimal(x) / scale_factor).rstrip('0').rstrip('.')
|
||||
|
||||
|
||||
def format_satoshis(x, is_diff=False, num_zeros = 0, decimal_point = 8, whitespaces=False):
|
||||
from locale import localeconv
|
||||
if x is None:
|
||||
@@ -277,7 +468,9 @@ def format_satoshis(x, is_diff=False, num_zeros = 0, decimal_point = 8, whitespa
|
||||
if whitespaces:
|
||||
result += " " * (decimal_point - len(fract_part))
|
||||
result = " " * (15 - len(result)) + result
|
||||
return result.decode('utf8')
|
||||
if six.PY2:
|
||||
result = result.decode('utf8')
|
||||
return result
|
||||
|
||||
def timestamp_to_datetime(timestamp):
|
||||
try:
|
||||
@@ -404,15 +597,15 @@ def block_explorer_URL(config, kind, item):
|
||||
#urldecode = lambda x: _ud.sub(lambda m: chr(int(m.group(1), 16)), x)
|
||||
|
||||
def parse_URI(uri, on_pr=None):
|
||||
import bitcoin
|
||||
from bitcoin import COIN
|
||||
from . import bitcoin
|
||||
from .bitcoin import COIN
|
||||
|
||||
if ':' not in uri:
|
||||
if not bitcoin.is_address(uri):
|
||||
raise BaseException("Not a bitcoin address")
|
||||
return {'address': uri}
|
||||
|
||||
u = urlparse.urlparse(uri)
|
||||
u = urllib_parse.urlparse(uri)
|
||||
if u.scheme != 'bitcoin':
|
||||
raise BaseException("Not a bitcoin URI")
|
||||
address = u.path
|
||||
@@ -420,9 +613,9 @@ def parse_URI(uri, on_pr=None):
|
||||
# python for android fails to parse query
|
||||
if address.find('?') > 0:
|
||||
address, query = u.path.split('?')
|
||||
pq = urlparse.parse_qs(query)
|
||||
pq = urllib_parse.parse_qs(query)
|
||||
else:
|
||||
pq = urlparse.parse_qs(u.query)
|
||||
pq = urllib_parse.parse_qs(u.query)
|
||||
|
||||
for k, v in pq.items():
|
||||
if len(v)!=1:
|
||||
@@ -443,21 +636,24 @@ def parse_URI(uri, on_pr=None):
|
||||
amount = Decimal(am) * COIN
|
||||
out['amount'] = int(amount)
|
||||
if 'message' in out:
|
||||
out['message'] = out['message'].decode('utf8')
|
||||
if six.PY3:
|
||||
out['message'] = out['message']
|
||||
else:
|
||||
out['message'] = out['message'].decode('utf8')
|
||||
out['memo'] = out['message']
|
||||
if 'time' in out:
|
||||
out['time'] = int(out['time'])
|
||||
if 'exp' in out:
|
||||
out['exp'] = int(out['exp'])
|
||||
if 'sig' in out:
|
||||
out['sig'] = bitcoin.base_decode(out['sig'], None, base=58).encode('hex')
|
||||
out['sig'] = bh2u(bitcoin.base_decode(out['sig'], None, base=58))
|
||||
|
||||
r = out.get('r')
|
||||
sig = out.get('sig')
|
||||
name = out.get('name')
|
||||
if on_pr and (r or (name and sig)):
|
||||
def get_payment_request_thread():
|
||||
import paymentrequest as pr
|
||||
from . import paymentrequest as pr
|
||||
if name and sig:
|
||||
s = pr.serialize_request(out).SerializeToString()
|
||||
request = pr.PaymentRequest(s)
|
||||
@@ -472,7 +668,7 @@ def parse_URI(uri, on_pr=None):
|
||||
|
||||
|
||||
def create_URI(addr, amount, message):
|
||||
import bitcoin
|
||||
from . import bitcoin
|
||||
if not bitcoin.is_address(addr):
|
||||
return ""
|
||||
query = []
|
||||
@@ -482,19 +678,26 @@ def create_URI(addr, amount, message):
|
||||
if type(message) == unicode:
|
||||
message = message.encode('utf8')
|
||||
query.append('message=%s'%urllib.quote(message))
|
||||
p = urlparse.ParseResult(scheme='bitcoin', netloc='', path=addr, params='', query='&'.join(query), fragment='')
|
||||
return urlparse.urlunparse(p)
|
||||
p = urllib_parse.ParseResult(scheme='bitcoin', netloc='', path=addr, params='', query='&'.join(query), fragment='')
|
||||
return urllib_parse.urlunparse(p)
|
||||
|
||||
|
||||
# Python bug (http://bugs.python.org/issue1927) causes raw_input
|
||||
# to be redirected improperly between stdin/stderr on Unix systems
|
||||
#TODO: py3
|
||||
def raw_input(prompt=None):
|
||||
if prompt:
|
||||
sys.stdout.write(prompt)
|
||||
return builtin_raw_input()
|
||||
import __builtin__
|
||||
builtin_raw_input = __builtin__.raw_input
|
||||
__builtin__.raw_input = raw_input
|
||||
|
||||
if six.PY2:
|
||||
import __builtin__
|
||||
builtin_raw_input = __builtin__.raw_input
|
||||
__builtin__.raw_input = raw_input
|
||||
else:
|
||||
import builtins
|
||||
builtin_raw_input = builtins.input
|
||||
builtins.input = raw_input
|
||||
|
||||
|
||||
|
||||
@@ -596,8 +799,6 @@ class SocketPipe:
|
||||
|
||||
|
||||
|
||||
import Queue
|
||||
|
||||
class QueuePipe:
|
||||
|
||||
def __init__(self, send_queue=None, get_queue=None):
|
||||
|
||||
Reference in New Issue
Block a user