Skip to content
This repository was archived by the owner on Jan 13, 2023. It is now read-only.

Commit 93f67cf

Browse files
authored
Merge pull request #30 from iotaledger/release/1.1.1
1.1.1
2 parents 569b052 + 00c903e commit 93f67cf

32 files changed

+1437
-288
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@ language: python
22
python:
33
- "2.7"
44
- "3.5"
5-
- "3.6-dev"
5+
- "3.6"
66
install: "pip install ."
77
script: "nosetests"

examples/address_generator.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,11 +86,11 @@ def output_seed(seed):
8686
parser.add_argument(
8787
'--uri',
8888
type = text_type,
89-
default = 'udp://localhost:14265/',
89+
default = 'http://localhost:14265/',
9090

9191
help =
9292
'URI of the node to connect to '
93-
'(defaults to udp://localhost:14265/).',
93+
'(defaults to http://localhost:14265/).',
9494
)
9595

9696
parser.add_argument(

examples/hello_world.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,11 @@ def main(uri):
4444
parser.add_argument(
4545
'--uri',
4646
type = text_type,
47-
default = 'udp://localhost:14265/',
47+
default = 'http://localhost:14265/',
4848

4949
help =
5050
'URI of the node to connect to '
51-
'(defaults to udp://localhost:14265/).',
51+
'(defaults to http://localhost:14265/).',
5252
)
5353

5454
main(**vars(parser.parse_args(argv[1:])))

examples/shell.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,7 @@
1919
from iota import __version__
2020
from iota.adapter import resolve_adapter
2121
from iota.adapter.wrappers import RoutingWrapper
22-
23-
24-
basicConfig(level=DEBUG, stream=stderr)
22+
from iota.crypto.addresses import AddressGenerator, MemoryAddressCache
2523

2624

2725
def main(uri, testnet, pow_uri, debug_requests):
@@ -47,12 +45,18 @@ def main(uri, testnet, pow_uri, debug_requests):
4745

4846
# If ``debug_requests`` is specified, log HTTP requests/responses.
4947
if debug_requests:
48+
basicConfig(level=DEBUG, stream=stderr)
49+
5050
logger = getLogger(__name__)
5151
logger.setLevel(DEBUG)
52+
5253
adapter_.set_logger(logger)
5354

5455
iota = Iota(adapter_, seed=seed, testnet=testnet)
5556

57+
# To speed up certain operations, install an address cache.
58+
AddressGenerator.cache = MemoryAddressCache()
59+
5660
_banner = (
5761
'IOTA API client for {uri} ({testnet}) initialized as variable `iota`.\n'
5862
'Type `help(iota)` for help.'.format(

setup.py

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,9 @@
55
from __future__ import absolute_import, division, print_function
66

77
from codecs import StreamReader, open
8-
from sys import version_info
98

109
from setuptools import find_packages, setup
1110

12-
##
13-
# Check Python version.
14-
if version_info[0:2] < (2, 7):
15-
raise EnvironmentError('PyOTA requires Python 2.7 or greater.')
16-
17-
if (version_info[0] == 3) and (version_info[1] < 5):
18-
raise EnvironmentError('PyOTA requires Python 3.5 or greater.')
19-
2011
##
2112
# Load long description for PyPi.
2213
with open('README.rst', 'r', 'utf-8') as f: # type: StreamReader
@@ -28,7 +19,7 @@
2819
name = 'PyOTA',
2920
description = 'IOTA API library for Python',
3021
url = 'https://github.com/iotaledger/iota.lib.py',
31-
version = '1.1.0',
22+
version = '1.1.1',
3223

3324
packages = find_packages('src'),
3425
include_package_data = True,
@@ -63,7 +54,9 @@
6354
'Topic :: Software Development :: Libraries :: Python Modules',
6455
],
6556

66-
keywords = 'iota,tangle,iot,internet of things,api,library',
57+
keywords =
58+
'iota,tangle,iot,internet of things,api,library,cryptocurrency,'
59+
'balanced ternary',
6760

6861
author = 'Phoenix Zerin',
6962
author_email = 'phx@phx.ph',

src/iota/adapter/__init__.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,11 @@ def _interpret_response(self, response, payload, expected_status):
332332
raw_content = response.text
333333
if not raw_content:
334334
raise with_context(
335-
exc = BadApiResponse('Empty response from node.'),
335+
exc = BadApiResponse(
336+
'Empty {status} response from node.'.format(
337+
status = response.status_code,
338+
),
339+
),
336340

337341
context = {
338342
'request': payload,
@@ -345,7 +349,8 @@ def _interpret_response(self, response, payload, expected_status):
345349
except ValueError:
346350
raise with_context(
347351
exc = BadApiResponse(
348-
'Non-JSON response from node: {raw_content}'.format(
352+
'Non-JSON {status} response from node: {raw_content}'.format(
353+
status = response.status_code,
349354
raw_content = raw_content,
350355
)
351356
),
@@ -359,7 +364,8 @@ def _interpret_response(self, response, payload, expected_status):
359364
if not isinstance(decoded, dict):
360365
raise with_context(
361366
exc = BadApiResponse(
362-
'Invalid response from node: {decoded!r}'.format(
367+
'Malformed {status} response from node: {decoded!r}'.format(
368+
status = response.status_code,
363369
decoded = decoded,
364370
),
365371
),

src/iota/adapter/sandbox.py

Lines changed: 67 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,19 @@ class SandboxAdapter(HttpAdapter):
4343
Number of seconds to wait between requests to check job status.
4444
"""
4545

46-
def __init__(self, uri, auth_token, poll_interval=DEFAULT_POLL_INTERVAL):
47-
# type: (Union[Text, SplitResult], Optional[Text], int) -> None
46+
DEFAULT_MAX_POLLS = 8
47+
"""
48+
Maximum number of times to poll for job status before giving up.
49+
"""
50+
51+
def __init__(
52+
self,
53+
uri,
54+
auth_token,
55+
poll_interval = DEFAULT_POLL_INTERVAL,
56+
max_polls = DEFAULT_MAX_POLLS,
57+
):
58+
# type: (Union[Text, SplitResult], Optional[Text], int, int) -> None
4859
"""
4960
:param uri:
5061
URI of the node to connect to.
@@ -73,6 +84,13 @@ def __init__(self, uri, auth_token, poll_interval=DEFAULT_POLL_INTERVAL):
7384
(once the node completes the job), but it increases traffic to
7485
the node (which may trip a rate limiter and/or incur additional
7586
costs).
87+
88+
:param max_polls:
89+
Max number of times to poll for job status before giving up.
90+
Must be a positive integer.
91+
92+
This is effectively a timeout setting for asynchronous jobs;
93+
multiply by ``poll_interval`` to get the timeout duration.
7694
"""
7795
super(SandboxAdapter, self).__init__(uri)
7896

@@ -119,7 +137,7 @@ def __init__(self, uri, auth_token, poll_interval=DEFAULT_POLL_INTERVAL):
119137
raise with_context(
120138
exc =
121139
ValueError(
122-
'``poll_interval`` must be >= 1 '
140+
'``poll_interval`` must be > 0 '
123141
'(``exc.context`` has more info).',
124142
),
125143

@@ -128,8 +146,35 @@ def __init__(self, uri, auth_token, poll_interval=DEFAULT_POLL_INTERVAL):
128146
},
129147
)
130148

149+
if not isinstance(max_polls, int):
150+
raise with_context(
151+
exc =
152+
TypeError(
153+
'``max_polls`` must be an int '
154+
'(``exc.context`` has more info).',
155+
),
156+
157+
context = {
158+
'max_polls': max_polls,
159+
},
160+
)
161+
162+
if max_polls < 1:
163+
raise with_context(
164+
exc =
165+
ValueError(
166+
'``max_polls`` must be > 0 '
167+
'(``exc.context`` has more info).',
168+
),
169+
170+
context = {
171+
'max_polls': max_polls,
172+
},
173+
)
174+
131175
self.auth_token = auth_token # type: Optional[Text]
132176
self.poll_interval = poll_interval # type: int
177+
self.max_polls = max_polls # type: int
133178

134179
@property
135180
def node_url(self):
@@ -185,8 +230,27 @@ def _interpret_response(self, response, payload, expected_status):
185230
# Check to see if the request was queued for asynchronous
186231
# execution.
187232
if response.status_code == codes['accepted']:
233+
poll_count = 0
188234
while decoded['status'] in (STATUS_QUEUED, STATUS_RUNNING):
235+
if poll_count >= self.max_polls:
236+
raise with_context(
237+
exc =
238+
BadApiResponse(
239+
'``{command}`` job timed out after {duration} seconds '
240+
'(``exc.context`` has more info).'.format(
241+
command = decoded['command'],
242+
duration = self.poll_interval * self.max_polls,
243+
),
244+
),
245+
246+
context = {
247+
'request': payload,
248+
'response': decoded,
249+
},
250+
)
251+
189252
self._wait_to_poll()
253+
poll_count += 1
190254

191255
poll_response = self._send_http_request(
192256
headers = {'Authorization': self.authorization_header},

0 commit comments

Comments
 (0)