Skip to content

Commit

Permalink
Documentation fixes
Browse files Browse the repository at this point in the history
Also make Ping internal state be internal
  • Loading branch information
dkfellows committed Mar 31, 2021
1 parent 7728491 commit 8c6f551
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 29 deletions.
14 changes: 11 additions & 3 deletions spinn_utilities/bytestring_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,14 @@ def as_string(bytestring, start=None, end=None):
The length is always the full length irrespective of the start and end.
:param bytestring: data as a bytestring
:param bytestring: data as a byte string
:type bytestring: bytes or bytearray or memoryview
:param start: the inclusive start of the slice to return. May be None
:type start: int or None
:param end: the exclusive end of the slice to return. May be None
:return: The length of the bytesting and the hex values, comma separated
:type end: int or None
:return: The length of the bytestring and the hex values, comma separated
:rtype: str
"""
return "(" + str(len(bytestring)) + ")" + as_hex(bytestring, start, end)

Expand All @@ -32,9 +36,13 @@ def as_hex(bytestring, start=None, end=None):
"""
Returns the bytestring as string showing the hex values
:param bytestring: data as a byteString
:param bytestring: data as a byte string
:type bytestring: bytes or bytearray or memoryview
:param start: the inclusive start of the slice to return. May be None
:type start: int or None
:param end: the exclusive end of the slice to return. May be None
:type end: int or None
:return: Comma separated hex values
:rtype: str
"""
return ','.join('%02x' % i for i in iter(bytestring[start:end]))
2 changes: 1 addition & 1 deletion spinn_utilities/helpful_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class names.
:param str terminator:
Regular expression string to match the suffix. Anchoring not required.
:return: mapping from (shortened) name to class
:rtype: dict(str -> class)
:rtype: dict(str, type)
"""
terminator_re = re.compile(terminator + '$')
return {terminator_re.sub('', name): router
Expand Down
5 changes: 1 addition & 4 deletions spinn_utilities/log.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,10 +172,7 @@ def set_kill_level(cls, level=None):
@classmethod
def set_report_File(cls, report_file):
"""
:param report_file:
:param write_normal:
:return:
:param str report_file:
"""
cls.__report_file = report_file
level = logging.getLevelName(cls.__repeat_at_end)
Expand Down
6 changes: 4 additions & 2 deletions spinn_utilities/package_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ def load_modules(
:param list(str) exclusions: a list of modules to exclude
:param bool gather_errors:
True if errors should be gathered, False to report on first error
:return: None
:raises Exception:
If anything goes wrong.
"""
if exclusions is None:
exclusions = []
Expand Down Expand Up @@ -110,7 +111,8 @@ def load_module(
:param list(str) exclusions: a list of modules to exclude
:param bool gather_errors:
True if errors should be gathered, False to report on first error
:return: None
:raises Exception:
If anything goes wrong.
"""
if exclusions is None:
exclusions = []
Expand Down
53 changes: 42 additions & 11 deletions spinn_utilities/ping.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,34 @@


class Ping(object):
unreachable = set()
"""
Tests for ICMP host reachability.
.. note::
A properly booted SpiNNaker machine is guaranteed to respond to ICMP
ECHO requests.
.. warning::
These tests are able to fail in several ways. In particular, some ISPs
make hosts appear to be reachable even when they are not, and some
environments (such as Azure, used by Github Actions) make hosts appear
unreachable even when actually connecting to them with TCP or UDP will
work. These are fundamental limitations relating to host resolution
and firewalls.
"""
_unreachable = set()
_MAX_TRIES = 10

@staticmethod
def ping(ipaddr):
"""
Wrapper around the system ``ping`` program.
:param str ipaddr:
The IP address (or host name) of the machine to ping.
:return: The program exit code.
:rtype: int
"""
if platform.platform().lower().startswith("windows"):
cmd = "ping -n 1 -w 1 "
else:
Expand All @@ -34,15 +58,22 @@ def ping(ipaddr):
process.wait()
return process.returncode

@staticmethod
def host_is_reachable(ipaddr):
if ipaddr in Ping.unreachable:
@classmethod
def host_is_reachable(cls, ipaddr):
"""
Wrapper for :py:meth:`ping` that converts numeric results into a
reachability decision, retries a few times in case a temporary network
glitch is occurring, and caches (slow) unreachability results.
:param str ipaddr:
The IP address (or host name) of the machine to ping.
:return: ``True`` if the machine is reachable.
:rtype: bool
"""
if ipaddr in cls._unreachable:
return False
tries = 0
while (True):
if Ping.ping(ipaddr) == 0:
for _try in range(cls._MAX_TRIES):
if cls.ping(ipaddr) == 0:
return True
tries += 1
if tries > 10:
Ping.unreachable.add(ipaddr)
return False
cls._unreachable.add(ipaddr)
return False
46 changes: 38 additions & 8 deletions spinn_utilities/progress_bar.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,16 @@


class ProgressBar(object):
""" Progress bar for telling the user where a task is up to
""" Progress bar for telling the user where a task is up to.
This is a context manager; you may use the progress bar like this::
with ProgressBar(...) as p:
...
p.update()
...
p.update()
...
"""
MAX_LENGTH_IN_CHARS = 60

Expand All @@ -46,6 +55,18 @@ class ProgressBar(object):
def __init__(self, total_number_of_things_to_do,
string_describing_what_being_progressed,
step_character="=", end_character="|"):
"""
:param total_number_of_things_to_do:
The number of steps (calls to :py:meth:`update`) expected,
or an iterable with that many elements.
:type total_number_of_things_to_do: int or ~collections.abc.Iterable
:param str string_describing_what_being_progressed:
The descriptive message to print associated with the progress bar.
:param str step_character:
Character to use for each step.
:param str end_character:
Character to use at each end of the progress bar.
"""
try:
self._number_of_things = int(total_number_of_things_to_do)
except TypeError:
Expand All @@ -71,8 +92,8 @@ def __init__(self, total_number_of_things_to_do,
def update(self, amount_to_add=1):
""" Update the progress bar by a given amount
:param amount_to_add:
:rtype: None
:param int amount_to_add:
How many steps to advance by.
"""

if self._currently_completed + amount_to_add > self._number_of_things:
Expand Down Expand Up @@ -153,8 +174,6 @@ def _check_differences(self):

def end(self):
""" Close the progress bar, updating whatever is left if needed
:rtype: None
"""
difference = self._number_of_things - self._currently_completed
self._currently_completed += difference
Expand All @@ -181,11 +200,16 @@ def __enter__(self):
Like :samp:`__new__` this method has to return self as in theory it
could pass back a different object. Welcome to Python.
:return: The Progress bar
:return: The progress bar
:rtype: ProgressBar
"""
return self

def __exit__(self, exty, exval, traceback): # @UnusedVariable
"""
Terminates the progress bar cleanly.
Tells Python to resume any exception in progress (if relevant).
"""
self.end()
return False

Expand All @@ -195,11 +219,13 @@ def over(self, collection, finish_at_end=True):
The progress bar should have been initialised to the size of the\
collection being iterated over.
:param collection:
:param ~collections.abc.Iterable collection:
The base collection (any iterable) being iterated over
:param bool finish_at_end:
Flag to say if the bar should finish at the end of the collection
:return: An iterable. Expected to be directly used in a for.
:return: An iterable of the values from ``collection``.
Expected to be directly used in a ``for`` loop.
:rtype: ~collections.abc.Iterable
"""
try:
for item in collection:
Expand Down Expand Up @@ -316,6 +342,10 @@ class DummyProgressBar(ProgressBar):
""" This is a dummy version of the progress bar that just stubs out the\
internal printing operations with code that does nothing. It otherwise\
fails in exactly the same way.
.. note::
Use this if you need a dummy or mock object to pass to something that
needs a progress bar, but where you do not want to print anything.
"""
@overrides(ProgressBar._print_overwritten_line)
def _print_overwritten_line(self, string):
Expand Down

0 comments on commit 8c6f551

Please sign in to comment.