Skip to content

Commit 260cf5c

Browse files
committed
Squashed 'qa/rpc-tests/python-bitcoinrpc/' content from commit e484743
git-subtree-dir: qa/rpc-tests/python-bitcoinrpc git-subtree-split: e48474322de165212c5aa29574297e78b09df8d6
1 parent 829f822 commit 260cf5c

File tree

9 files changed

+193
-0
lines changed

9 files changed

+193
-0
lines changed

README

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
AuthServiceProxy is an improved version of python-jsonrpc.
2+
3+
It includes the following generic improvements:
4+
5+
- HTTP connections persist for the life of the AuthServiceProxy object
6+
- sends protocol 'version', per JSON-RPC 1.1
7+
- sends proper, incrementing 'id'
8+
- uses standard Python json lib
9+
10+
It also includes the following bitcoin-specific details:
11+
12+
- sends Basic HTTP authentication headers
13+
- parses all JSON numbers that look like floats as Decimal
14+
15+
Installation:
16+
17+
- change the first line of setup.py to point to the directory of your installation of python 2.*
18+
- run setup.py
19+
20+
Note: This will only install bitcoinrpc. If you also want to install jsonrpc to preserve
21+
backwards compatibility, you have to replace 'bitcoinrpc' with 'jsonrpc' in setup.py and run it again.

bitcoinrpc/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
*.pyc
2+

bitcoinrpc/__init__.py

Whitespace-only changes.

bitcoinrpc/authproxy.py

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
2+
"""
3+
Copyright 2011 Jeff Garzik
4+
5+
AuthServiceProxy has the following improvements over python-jsonrpc's
6+
ServiceProxy class:
7+
8+
- HTTP connections persist for the life of the AuthServiceProxy object
9+
(if server supports HTTP/1.1)
10+
- sends protocol 'version', per JSON-RPC 1.1
11+
- sends proper, incrementing 'id'
12+
- sends Basic HTTP authentication headers
13+
- parses all JSON numbers that look like floats as Decimal
14+
- uses standard Python json lib
15+
16+
Previous copyright, from python-jsonrpc/jsonrpc/proxy.py:
17+
18+
Copyright (c) 2007 Jan-Klaas Kollhof
19+
20+
This file is part of jsonrpc.
21+
22+
jsonrpc is free software; you can redistribute it and/or modify
23+
it under the terms of the GNU Lesser General Public License as published by
24+
the Free Software Foundation; either version 2.1 of the License, or
25+
(at your option) any later version.
26+
27+
This software is distributed in the hope that it will be useful,
28+
but WITHOUT ANY WARRANTY; without even the implied warranty of
29+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30+
GNU Lesser General Public License for more details.
31+
32+
You should have received a copy of the GNU Lesser General Public License
33+
along with this software; if not, write to the Free Software
34+
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
35+
"""
36+
37+
try:
38+
import http.client as httplib
39+
except ImportError:
40+
import httplib
41+
import base64
42+
import json
43+
import decimal
44+
try:
45+
import urllib.parse as urlparse
46+
except ImportError:
47+
import urlparse
48+
49+
USER_AGENT = "AuthServiceProxy/0.1"
50+
51+
HTTP_TIMEOUT = 30
52+
53+
54+
class JSONRPCException(Exception):
55+
def __init__(self, rpc_error):
56+
Exception.__init__(self)
57+
self.error = rpc_error
58+
59+
60+
class AuthServiceProxy(object):
61+
def __init__(self, service_url, service_name=None, timeout=HTTP_TIMEOUT, connection=None):
62+
self.__service_url = service_url
63+
self.__service_name = service_name
64+
self.__url = urlparse.urlparse(service_url)
65+
if self.__url.port is None:
66+
port = 80
67+
else:
68+
port = self.__url.port
69+
self.__id_count = 0
70+
(user, passwd) = (self.__url.username, self.__url.password)
71+
try:
72+
user = user.encode('utf8')
73+
except AttributeError:
74+
pass
75+
try:
76+
passwd = passwd.encode('utf8')
77+
except AttributeError:
78+
pass
79+
authpair = user + b':' + passwd
80+
self.__auth_header = b'Basic ' + base64.b64encode(authpair)
81+
82+
if connection:
83+
# Callables re-use the connection of the original proxy
84+
self.__conn = connection
85+
elif self.__url.scheme == 'https':
86+
self.__conn = httplib.HTTPSConnection(self.__url.hostname, port,
87+
None, None, False,
88+
timeout)
89+
else:
90+
self.__conn = httplib.HTTPConnection(self.__url.hostname, port,
91+
False, timeout)
92+
93+
def __getattr__(self, name):
94+
if name.startswith('__') and name.endswith('__'):
95+
# Python internal stuff
96+
raise AttributeError
97+
if self.__service_name is not None:
98+
name = "%s.%s" % (self.__service_name, name)
99+
return AuthServiceProxy(self.__service_url, name, connection=self.__conn)
100+
101+
def __call__(self, *args):
102+
self.__id_count += 1
103+
104+
postdata = json.dumps({'version': '1.1',
105+
'method': self.__service_name,
106+
'params': args,
107+
'id': self.__id_count})
108+
self.__conn.request('POST', self.__url.path, postdata,
109+
{'Host': self.__url.hostname,
110+
'User-Agent': USER_AGENT,
111+
'Authorization': self.__auth_header,
112+
'Content-type': 'application/json'})
113+
114+
response = self._get_response()
115+
if response['error'] is not None:
116+
raise JSONRPCException(response['error'])
117+
elif 'result' not in response:
118+
raise JSONRPCException({
119+
'code': -343, 'message': 'missing JSON-RPC result'})
120+
else:
121+
return response['result']
122+
123+
def _batch(self, rpc_call_list):
124+
postdata = json.dumps(list(rpc_call_list))
125+
self.__conn.request('POST', self.__url.path, postdata,
126+
{'Host': self.__url.hostname,
127+
'User-Agent': USER_AGENT,
128+
'Authorization': self.__auth_header,
129+
'Content-type': 'application/json'})
130+
131+
return self._get_response()
132+
133+
def _get_response(self):
134+
http_response = self.__conn.getresponse()
135+
if http_response is None:
136+
raise JSONRPCException({
137+
'code': -342, 'message': 'missing HTTP response from server'})
138+
139+
return json.loads(http_response.read().decode('utf8'),
140+
parse_float=decimal.Decimal)

jsonrpc/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
from .json import loads, dumps, JSONEncodeException, JSONDecodeException
2+
from jsonrpc.proxy import ServiceProxy, JSONRPCException

jsonrpc/authproxy.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException
2+
3+
__all__ = ['AuthServiceProxy', 'JSONRPCException']

jsonrpc/json.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
_json = __import__('json')
2+
loads = _json.loads
3+
dumps = _json.dumps
4+
if hasattr(_json, 'JSONEncodeException'):
5+
JSONEncodeException = _json.JSONEncodeException
6+
JSONDecodeException = _json.JSONDecodeException
7+
else:
8+
JSONEncodeException = TypeError
9+
JSONDecodeException = ValueError

jsonrpc/proxy.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from bitcoinrpc.authproxy import AuthServiceProxy as ServiceProxy, JSONRPCException

setup.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#!/usr/bin/env python
2+
3+
from distutils.core import setup
4+
5+
setup(name='python-bitcoinrpc',
6+
version='0.1',
7+
description='Enhanced version of python-jsonrpc for use with Bitcoin',
8+
long_description=open('README').read(),
9+
author='Jeff Garzik',
10+
author_email='<[email protected]>',
11+
maintainer='Jeff Garzik',
12+
maintainer_email='<[email protected]>',
13+
url='http://www.github.com/jgarzik/python-bitcoinrpc',
14+
packages=['bitcoinrpc'],
15+
classifiers=['License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)', 'Operating System :: OS Independent'])

0 commit comments

Comments
 (0)