Changeset View
Changeset View
Standalone View
Standalone View
net/py-python-bitcoinrpc/files/patch-f607fe7
- This file was added.
Property | Old Value | New Value |
---|---|---|
fbsd:nokeywords | null | yes \ No newline at end of property |
svn:eol-style | null | native \ No newline at end of property |
svn:mime-type | null | text/plain \ No newline at end of property |
--- .gitignore.orig 2015-08-06 06:33:27 UTC | |||||
+++ .gitignore | |||||
@@ -0,0 +1,4 @@ | |||||
+*.pyc | |||||
+ | |||||
+MANIFEST | |||||
+dist/ | |||||
--- README.orig 2011-04-06 19:53:31 UTC | |||||
+++ README | |||||
@@ -1,4 +1,3 @@ | |||||
- | |||||
AuthServiceProxy is an improved version of python-jsonrpc. | |||||
It includes the following generic improvements: | |||||
@@ -7,9 +6,51 @@ It includes the following generic improv | |||||
- sends protocol 'version', per JSON-RPC 1.1 | |||||
- sends proper, incrementing 'id' | |||||
- uses standard Python json lib | |||||
+- can optionally log all RPC calls and results | |||||
+- JSON-2.0 batch support | |||||
It also includes the following bitcoin-specific details: | |||||
- sends Basic HTTP authentication headers | |||||
-- parses all JSON numbers that look like floats as Decimal | |||||
+- parses all JSON numbers that look like floats as Decimal, | |||||
+ and serializes Decimal values to JSON-RPC connections. | |||||
+ | |||||
+Installation: | |||||
+ | |||||
+- change the first line of setup.py to point to the directory of your installation of python 2.* | |||||
+- run setup.py | |||||
+ | |||||
+Note: This will only install bitcoinrpc. If you also want to install jsonrpc to preserve | |||||
+backwards compatibility, you have to replace 'bitcoinrpc' with 'jsonrpc' in setup.py and run it again. | |||||
+ | |||||
+Example usage: | |||||
+ | |||||
+ from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException | |||||
+ | |||||
+ # rpc_user and rpc_password are set in the bitcoin.conf file | |||||
+ rpc_connection = AuthServiceProxy("http://%s:%s@127.0.0.1:8332"%(rpc_user, rpc_password)) | |||||
+ best_block_hash = rpc_connection.getbestblockhash() | |||||
+ print(rpc_connection.getblock(best_block_hash)) | |||||
+ # batch support : print timestamps of blocks 0 to 99 in 2 RPC round-trips: | |||||
+ commands = [ [ "getblockhash", height] for height in range(100) ] | |||||
+ block_hashes = rpc_connection.batch_(commands) | |||||
+ blocks = rpc_connection.batch_([ [ "getblock", h ] for h in block_hashes ]) | |||||
+ block_times = [ block["time"] for block in blocks ] | |||||
+ print(block_times) | |||||
+ | |||||
+Logging all RPC calls to stderr: | |||||
+ | |||||
+ from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException | |||||
+ import logging | |||||
+ | |||||
+ logging.basicConfig() | |||||
+ logging.getLogger("BitcoinRPC").setLevel(logging.DEBUG) | |||||
+ | |||||
+ rpc_connection = AuthServiceProxy("http://%s:%s@127.0.0.1:8332"%(rpc_user, rpc_password)) | |||||
+ print(rpc_connection.getinfo()) | |||||
+ | |||||
+Produces output on stderr like: | |||||
+ | |||||
+ DEBUG:BitcoinRPC:-1-> getinfo [] | |||||
+ DEBUG:BitcoinRPC:<-1- {"connections": 8, ...etc } | |||||
--- bitcoinrpc/.gitignore.orig 2015-08-06 06:33:27 UTC | |||||
+++ bitcoinrpc/.gitignore | |||||
@@ -0,0 +1,2 @@ | |||||
+*.pyc | |||||
+ | |||||
--- bitcoinrpc/authproxy.py.orig 2015-08-06 06:33:27 UTC | |||||
+++ bitcoinrpc/authproxy.py | |||||
@@ -0,0 +1,187 @@ | |||||
+ | |||||
+""" | |||||
+ Copyright 2011 Jeff Garzik | |||||
+ | |||||
+ AuthServiceProxy has the following improvements over python-jsonrpc's | |||||
+ ServiceProxy class: | |||||
+ | |||||
+ - HTTP connections persist for the life of the AuthServiceProxy object | |||||
+ (if server supports HTTP/1.1) | |||||
+ - sends protocol 'version', per JSON-RPC 1.1 | |||||
+ - sends proper, incrementing 'id' | |||||
+ - sends Basic HTTP authentication headers | |||||
+ - parses all JSON numbers that look like floats as Decimal | |||||
+ - uses standard Python json lib | |||||
+ | |||||
+ Previous copyright, from python-jsonrpc/jsonrpc/proxy.py: | |||||
+ | |||||
+ Copyright (c) 2007 Jan-Klaas Kollhof | |||||
+ | |||||
+ This file is part of jsonrpc. | |||||
+ | |||||
+ jsonrpc is free software; you can redistribute it and/or modify | |||||
+ it under the terms of the GNU Lesser General Public License as published by | |||||
+ the Free Software Foundation; either version 2.1 of the License, or | |||||
+ (at your option) any later version. | |||||
+ | |||||
+ This software is distributed in the hope that it will be useful, | |||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
+ GNU Lesser General Public License for more details. | |||||
+ | |||||
+ You should have received a copy of the GNU Lesser General Public License | |||||
+ along with this software; if not, write to the Free Software | |||||
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |||||
+""" | |||||
+ | |||||
+try: | |||||
+ import http.client as httplib | |||||
+except ImportError: | |||||
+ import httplib | |||||
+import base64 | |||||
+import decimal | |||||
+import json | |||||
+import logging | |||||
+try: | |||||
+ import urllib.parse as urlparse | |||||
+except ImportError: | |||||
+ import urlparse | |||||
+ | |||||
+USER_AGENT = "AuthServiceProxy/0.1" | |||||
+ | |||||
+HTTP_TIMEOUT = 30 | |||||
+ | |||||
+log = logging.getLogger("BitcoinRPC") | |||||
+ | |||||
+class JSONRPCException(Exception): | |||||
+ def __init__(self, rpc_error): | |||||
+ parent_args = [] | |||||
+ try: | |||||
+ parent_args.append(rpc_error['message']) | |||||
+ except: | |||||
+ pass | |||||
+ Exception.__init__(self, *parent_args) | |||||
+ self.error = rpc_error | |||||
+ self.code = rpc_error['code'] if 'code' in rpc_error else None | |||||
+ self.message = rpc_error['message'] if 'message' in rpc_error else None | |||||
+ | |||||
+ def __str__(self): | |||||
+ return '%d: %s' % (self.code, self.message) | |||||
+ | |||||
+ def __repr__(self): | |||||
+ return '<%s \'%s\'>' % (self.__class__.__name__, self) | |||||
+ | |||||
+ | |||||
+def EncodeDecimal(o): | |||||
+ if isinstance(o, decimal.Decimal): | |||||
+ return round(o, 8) | |||||
+ raise TypeError(repr(o) + " is not JSON serializable") | |||||
+ | |||||
+class AuthServiceProxy(object): | |||||
+ __id_count = 0 | |||||
+ | |||||
+ def __init__(self, service_url, service_name=None, timeout=HTTP_TIMEOUT, connection=None): | |||||
+ self.__service_url = service_url | |||||
+ self.__service_name = service_name | |||||
+ self.__url = urlparse.urlparse(service_url) | |||||
+ if self.__url.port is None: | |||||
+ port = 80 | |||||
+ else: | |||||
+ port = self.__url.port | |||||
+ (user, passwd) = (self.__url.username, self.__url.password) | |||||
+ try: | |||||
+ user = user.encode('utf8') | |||||
+ except AttributeError: | |||||
+ pass | |||||
+ try: | |||||
+ passwd = passwd.encode('utf8') | |||||
+ except AttributeError: | |||||
+ pass | |||||
+ authpair = user + b':' + passwd | |||||
+ self.__auth_header = b'Basic ' + base64.b64encode(authpair) | |||||
+ | |||||
+ if connection: | |||||
+ # Callables re-use the connection of the original proxy | |||||
+ self.__conn = connection | |||||
+ elif self.__url.scheme == 'https': | |||||
+ self.__conn = httplib.HTTPSConnection(self.__url.hostname, port, | |||||
+ timeout=timeout) | |||||
+ else: | |||||
+ self.__conn = httplib.HTTPConnection(self.__url.hostname, port, | |||||
+ timeout=timeout) | |||||
+ | |||||
+ def __getattr__(self, name): | |||||
+ if name.startswith('__') and name.endswith('__'): | |||||
+ # Python internal stuff | |||||
+ raise AttributeError | |||||
+ if self.__service_name is not None: | |||||
+ name = "%s.%s" % (self.__service_name, name) | |||||
+ return AuthServiceProxy(self.__service_url, name, connection=self.__conn) | |||||
+ | |||||
+ def __call__(self, *args): | |||||
+ AuthServiceProxy.__id_count += 1 | |||||
+ | |||||
+ log.debug("-%s-> %s %s"%(AuthServiceProxy.__id_count, self.__service_name, | |||||
+ json.dumps(args, default=EncodeDecimal))) | |||||
+ postdata = json.dumps({'version': '1.1', | |||||
+ 'method': self.__service_name, | |||||
+ 'params': args, | |||||
+ 'id': AuthServiceProxy.__id_count}, default=EncodeDecimal) | |||||
+ self.__conn.request('POST', self.__url.path, postdata, | |||||
+ {'Host': self.__url.hostname, | |||||
+ 'User-Agent': USER_AGENT, | |||||
+ 'Authorization': self.__auth_header, | |||||
+ 'Content-type': 'application/json'}) | |||||
+ | |||||
+ response = self._get_response() | |||||
+ if response['error'] is not None: | |||||
+ raise JSONRPCException(response['error']) | |||||
+ elif 'result' not in response: | |||||
+ raise JSONRPCException({ | |||||
+ 'code': -343, 'message': 'missing JSON-RPC result'}) | |||||
+ else: | |||||
+ return response['result'] | |||||
+ | |||||
+ def batch_(self, rpc_calls): | |||||
+ """Batch RPC call. | |||||
+ Pass array of arrays: [ [ "method", params... ], ... ] | |||||
+ Returns array of results. | |||||
+ """ | |||||
+ batch_data = [] | |||||
+ for rpc_call in rpc_calls: | |||||
+ AuthServiceProxy.__id_count += 1 | |||||
+ m = rpc_call.pop(0) | |||||
+ batch_data.append({"jsonrpc":"2.0", "method":m, "params":rpc_call, "id":AuthServiceProxy.__id_count}) | |||||
+ | |||||
+ postdata = json.dumps(batch_data, default=EncodeDecimal) | |||||
+ log.debug("--> "+postdata) | |||||
+ self.__conn.request('POST', self.__url.path, postdata, | |||||
+ {'Host': self.__url.hostname, | |||||
+ 'User-Agent': USER_AGENT, | |||||
+ 'Authorization': self.__auth_header, | |||||
+ 'Content-type': 'application/json'}) | |||||
+ results = [] | |||||
+ responses = self._get_response() | |||||
+ for response in responses: | |||||
+ if response['error'] is not None: | |||||
+ raise JSONRPCException(response['error']) | |||||
+ elif 'result' not in response: | |||||
+ raise JSONRPCException({ | |||||
+ 'code': -343, 'message': 'missing JSON-RPC result'}) | |||||
+ else: | |||||
+ results.append(response['result']) | |||||
+ return results | |||||
+ | |||||
+ def _get_response(self): | |||||
+ http_response = self.__conn.getresponse() | |||||
+ if http_response is None: | |||||
+ raise JSONRPCException({ | |||||
+ 'code': -342, 'message': 'missing HTTP response from server'}) | |||||
+ | |||||
+ responsedata = http_response.read().decode('utf8') | |||||
+ response = json.loads(responsedata, parse_float=decimal.Decimal) | |||||
+ if "error" in response and response["error"] is None: | |||||
+ log.debug("<-%s- %s"%(response["id"], json.dumps(response["result"], default=EncodeDecimal))) | |||||
+ else: | |||||
+ log.debug("<-- "+responsedata) | |||||
+ return response | |||||
--- jsonrpc/__init__.py.orig 2011-04-06 19:53:31 UTC | |||||
+++ jsonrpc/__init__.py | |||||
@@ -1,2 +1,2 @@ | |||||
-from jsonrpc.json import loads, dumps, JSONEncodeException, JSONDecodeException | |||||
+from .json import loads, dumps, JSONEncodeException, JSONDecodeException | |||||
from jsonrpc.proxy import ServiceProxy, JSONRPCException | |||||
--- jsonrpc/authproxy.py.orig 2011-04-06 19:53:31 UTC | |||||
+++ jsonrpc/authproxy.py | |||||
@@ -1,100 +1,3 @@ | |||||
+from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException | |||||
-""" | |||||
- Copyright 2011 Jeff Garzik | |||||
- | |||||
- AuthServiceProxy has the following improvements over python-jsonrpc's | |||||
- ServiceProxy class: | |||||
- | |||||
- - HTTP connections persist for the life of the AuthServiceProxy object | |||||
- (if server supports HTTP/1.1) | |||||
- - sends protocol 'version', per JSON-RPC 1.1 | |||||
- - sends proper, incrementing 'id' | |||||
- - sends Basic HTTP authentication headers | |||||
- - parses all JSON numbers that look like floats as Decimal | |||||
- - uses standard Python json lib | |||||
- | |||||
- Previous copyright, from python-jsonrpc/jsonrpc/proxy.py: | |||||
- | |||||
- Copyright (c) 2007 Jan-Klaas Kollhof | |||||
- | |||||
- This file is part of jsonrpc. | |||||
- | |||||
- jsonrpc is free software; you can redistribute it and/or modify | |||||
- it under the terms of the GNU Lesser General Public License as published by | |||||
- the Free Software Foundation; either version 2.1 of the License, or | |||||
- (at your option) any later version. | |||||
- | |||||
- This software is distributed in the hope that it will be useful, | |||||
- but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
- GNU Lesser General Public License for more details. | |||||
- | |||||
- You should have received a copy of the GNU Lesser General Public License | |||||
- along with this software; if not, write to the Free Software | |||||
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |||||
-""" | |||||
- | |||||
-import httplib | |||||
-import base64 | |||||
-import json | |||||
-import decimal | |||||
-import urlparse | |||||
- | |||||
-USER_AGENT = "AuthServiceProxy/0.1" | |||||
- | |||||
-HTTP_TIMEOUT = 30 | |||||
- | |||||
-class JSONRPCException(Exception): | |||||
- def __init__(self, rpcError): | |||||
- Exception.__init__(self) | |||||
- self.error = rpcError | |||||
- | |||||
-class AuthServiceProxy(object): | |||||
- def __init__(self, serviceURL, serviceName=None): | |||||
- self.__serviceURL = serviceURL | |||||
- self.__serviceName = serviceName | |||||
- self.__url = urlparse.urlparse(serviceURL) | |||||
- if self.__url.port is None: | |||||
- port = 80 | |||||
- else: | |||||
- port = self.__url.port | |||||
- self.__idcnt = 0 | |||||
- authpair = "%s:%s" % (self.__url.username, self.__url.password) | |||||
- self.__authhdr = "Basic %s" % (base64.b64encode(authpair)) | |||||
- self.__conn = httplib.HTTPConnection(self.__url.hostname, port, False, | |||||
- HTTP_TIMEOUT) | |||||
- | |||||
- def __getattr__(self, name): | |||||
- if self.__serviceName != None: | |||||
- name = "%s.%s" % (self.__serviceName, name) | |||||
- return AuthServiceProxy(self.__serviceURL, name) | |||||
- | |||||
- def __call__(self, *args): | |||||
- self.__idcnt += 1 | |||||
- | |||||
- postdata = json.dumps({ | |||||
- 'version': '1.1', | |||||
- 'method': self.__serviceName, | |||||
- 'params': args, | |||||
- 'id': self.__idcnt}) | |||||
- self.__conn.request('POST', self.__url.path, postdata, | |||||
- { 'Host' : self.__url.hostname, | |||||
- 'User-Agent' : USER_AGENT, | |||||
- 'Authorization' : self.__authhdr, | |||||
- 'Content-type' : 'application/json' }) | |||||
- | |||||
- httpresp = self.__conn.getresponse() | |||||
- if httpresp is None: | |||||
- raise JSONRPCException({ | |||||
- 'code' : -342, 'message' : 'missing HTTP response from server'}) | |||||
- | |||||
- resp = json.loads(httpresp.read(), parse_float=decimal.Decimal) | |||||
- if resp['error'] != None: | |||||
- raise JSONRPCException(resp['error']) | |||||
- elif 'result' not in resp: | |||||
- raise JSONRPCException({ | |||||
- 'code' : -343, 'message' : 'missing JSON-RPC result'}) | |||||
- else: | |||||
- return resp['result'] | |||||
- | |||||
- | |||||
+__all__ = ['AuthServiceProxy', 'JSONRPCException'] | |||||
--- jsonrpc/json.py.orig 2011-04-06 19:53:31 UTC | |||||
+++ jsonrpc/json.py | |||||
@@ -1,5 +1,9 @@ | |||||
-json = __import__('json') | |||||
-loads = json.loads | |||||
-dumps = json.dumps | |||||
-JSONEncodeException = TypeError | |||||
-JSONDecodeException = ValueError | |||||
+_json = __import__('json') | |||||
+loads = _json.loads | |||||
+dumps = _json.dumps | |||||
+if hasattr(_json, 'JSONEncodeException'): | |||||
+ JSONEncodeException = _json.JSONEncodeException | |||||
+ JSONDecodeException = _json.JSONDecodeException | |||||
+else: | |||||
+ JSONEncodeException = TypeError | |||||
+ JSONDecodeException = ValueError | |||||
--- jsonrpc/proxy.py.orig 2011-04-06 19:53:31 UTC | |||||
+++ jsonrpc/proxy.py | |||||
@@ -1 +1 @@ | |||||
-from authproxy import AuthServiceProxy as ServiceProxy, JSONRPCException | |||||
+from bitcoinrpc.authproxy import AuthServiceProxy as ServiceProxy, JSONRPCException | |||||
--- setup.py.orig 2015-08-06 06:33:27 UTC | |||||
+++ setup.py | |||||
@@ -0,0 +1,15 @@ | |||||
+#!/usr/bin/env python | |||||
+ | |||||
+from distutils.core import setup | |||||
+ | |||||
+setup(name='python-bitcoinrpc', | |||||
+ version='0.1', | |||||
+ description='Enhanced version of python-jsonrpc for use with Bitcoin', | |||||
+ long_description=open('README').read(), | |||||
+ author='Jeff Garzik', | |||||
+ author_email='<jgarzik@exmulti.com>', | |||||
+ maintainer='Jeff Garzik', | |||||
+ maintainer_email='<jgarzik@exmulti.com>', | |||||
+ url='http://www.github.com/jgarzik/python-bitcoinrpc', | |||||
+ packages=['bitcoinrpc'], | |||||
+ classifiers=['License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)', 'Operating System :: OS Independent']) |