Skip to content

Commit

Permalink
Merge branch 'master' into minor-import-improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
dkfellows committed Sep 26, 2018
2 parents a0f68c0 + f498ce2 commit ce3b32d
Show file tree
Hide file tree
Showing 13 changed files with 143 additions and 110 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ before_install:
install:
- python setup.py develop
- pip install -r requirements-test.txt
- pip install python-coveralls
- pip install python-coveralls 'coverage>=4.4'
script:
- py.test tests/ --cov spalloc --cov tests --durations=10 --timeout=120
# Code quality check
Expand Down
9 changes: 6 additions & 3 deletions spalloc/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,24 @@


def time_left(timestamp):
"""Convert a timestamp into how long to wait for it."""
""" Convert a timestamp into how long to wait for it.
"""
if timestamp is None:
return None
return max(0.0, timestamp - time.time())


def timed_out(timestamp):
"""Check if a timestamp has been reached."""
""" Check if a timestamp has been reached.
"""
if timestamp is None:
return False
return timestamp < time.time()


def make_timeout(delay_seconds):
"""Convert a delay (in seconds) into a timestamp."""
""" Convert a delay (in seconds) into a timestamp.
"""
if delay_seconds is None:
return None
return time.time() + delay_seconds
4 changes: 2 additions & 2 deletions spalloc/config.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""The spalloc command-line tool and Python library determine their default
""" The spalloc command-line tool and Python library determine their default
configuration options from a spalloc configuration file if present.
.. note::
Expand Down Expand Up @@ -126,7 +126,7 @@ def _read_none_or_str(parser, option):


def read_config(filenames=None):
"""Attempt to read local configuration files to determine spalloc client
""" Attempt to read local configuration files to determine spalloc client
settings.
Parameters
Expand Down
79 changes: 45 additions & 34 deletions spalloc/job.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""A high-level Python interface for allocating SpiNNaker boards."""
""" A high-level Python interface for allocating SpiNNaker boards.
"""

from collections import namedtuple
import logging
Expand All @@ -22,7 +23,7 @@


class Job(object):
"""A high-level interface for requesting and managing allocations of
""" A high-level interface for requesting and managing allocations of
SpiNNaker boards.
Constructing a :py:class:`.Job` object connects to a `spalloc-server
Expand Down Expand Up @@ -106,7 +107,7 @@ class Job(object):
"""

def __init__(self, *args, **kwargs):
"""Request a SpiNNaker machine.
""" Request a SpiNNaker machine.
A :py:class:`.Job` is constructed in one of the following styles::
Expand Down Expand Up @@ -303,8 +304,8 @@ def __init__(self, *args, **kwargs):
self._reconnect_delay]), stdin=subprocess.PIPE)

def __enter__(self):
"""Convenience context manager for common case where a new job is to be
created and then destroyed once some code has executed.
""" Convenience context manager for common case where a new job is to
be created and then destroyed once some code has executed.
Waits for machine to be ready before the context enters and frees the
allocation when the context exits.
Expand All @@ -329,7 +330,8 @@ def __exit__(self, _type, _value, _traceback):
return False

def _assert_compatible_version(self):
"""Assert that the server version is compatible."""
""" Assert that the server version is compatible.
"""
v = self._client.version(timeout=self._timeout)
v_ints = tuple(map(int, v.split(".")[:3]))

Expand All @@ -340,7 +342,7 @@ def _assert_compatible_version(self):
v))

def _reconnect(self):
"""Reconnect to the server and check version.
""" Reconnect to the server and check version.
If reconnection fails, the error is reported as a warning but no
exception is raised.
Expand All @@ -357,7 +359,7 @@ def _reconnect(self):
self._client.close()

def destroy(self, reason=None):
"""Destroy the job and disconnect from the server.
""" Destroy the job and disconnect from the server.
Parameters
----------
Expand All @@ -376,7 +378,7 @@ def destroy(self, reason=None):
self.close()

def close(self):
"""Disconnect from the server and stop keeping the job alive.
""" Disconnect from the server and stop keeping the job alive.
.. warning::
Expand All @@ -394,7 +396,7 @@ def close(self):
self._client.close()

def _get_state(self):
"""Get the state of the job.
""" Get the state of the job.
Returns
-------
Expand All @@ -408,7 +410,7 @@ def _get_state(self):
reason=state["reason"])

def set_power(self, power):
"""Turn the boards allocated to the job on or off.
""" Turn the boards allocated to the job on or off.
Does nothing if the job has not yet been allocated any boards.
Expand All @@ -427,7 +429,7 @@ def set_power(self, power):
self._client.power_off_job_boards(self.id, timeout=self._timeout)

def reset(self):
"""Reset (power-cycle) the boards allocated to the job.
""" Reset (power-cycle) the boards allocated to the job.
Does nothing if the job has not been allocated.
Expand All @@ -437,7 +439,7 @@ def reset(self):
self.set_power(True)

def _get_machine_info(self):
"""Get information about the boards allocated to the job, e.g. the IPs
""" Get information about the boards allocated to the job, e.g. the IPs
and system dimensions.
Returns
Expand All @@ -459,25 +461,28 @@ def _get_machine_info(self):

@property
def state(self):
"""The current state of the job."""
""" The current state of the job.
"""
self._last_state = self._get_state()
return self._last_state.state

@property
def power(self):
"""Are the boards powered/powering on or off?"""
""" Are the boards powered/powering on or off?
"""
self._last_state = self._get_state()
return self._last_state.power

@property
def reason(self):
"""For what reason was the job destroyed (if any and if destroyed)."""
""" For what reason was the job destroyed (if any and if destroyed).
"""
self._last_state = self._get_state()
return self._last_state.reason

@property
def connections(self):
"""The list of Ethernet connected chips and their IPs.
""" The list of Ethernet connected chips and their IPs.
Returns
-------
Expand All @@ -493,12 +498,14 @@ def connections(self):

@property
def hostname(self):
"""The hostname of chip 0, 0 (or None if not allocated yet)."""
""" The hostname of chip 0, 0 (or None if not allocated yet).
"""
return self.connections[(0, 0)]

@property
def width(self):
"""The width of the allocated machine in chips (or None)."""
""" The width of the allocated machine in chips (or None).
"""
# Note that the dimensions of a job will never change once defined so
# only need to get this once.
if (self._last_machine_info is None or
Expand All @@ -509,7 +516,8 @@ def width(self):

@property
def height(self):
"""The height of the allocated machine in chips (or None)."""
""" The height of the allocated machine in chips (or None).
"""
# Note that the dimensions of a job will never change once defined so
# only need to get this once.
if (self._last_machine_info is None or
Expand All @@ -520,7 +528,8 @@ def height(self):

@property
def machine_name(self):
"""The name of the machine the job is allocated on (or None)."""
""" The name of the machine the job is allocated on (or None).
"""
# Note that the machine will never change once defined so only need to
# get this once.
if (self._last_machine_info is None or
Expand All @@ -531,7 +540,8 @@ def machine_name(self):

@property
def boards(self):
"""The coordinates of the boards allocated for the job (or None)."""
""" The coordinates of the boards allocated for the job (or None).
"""
# Note that the machine will never change once defined so only need to
# get this once.
if (self._last_machine_info is None or
Expand All @@ -541,7 +551,7 @@ def boards(self):
return self._last_machine_info.boards

def wait_for_state_change(self, old_state, timeout=None):
"""Block until the job's state changes from the supplied state.
""" Block until the job's state changes from the supplied state.
Parameters
----------
Expand Down Expand Up @@ -587,7 +597,7 @@ def wait_for_state_change(self, old_state, timeout=None):
return old_state

def _do_wait_for_a_change(self, finish_time):
"""Wait for a state change and keep the job alive.
""" Wait for a state change and keep the job alive.
"""
# Since we're about to block holding the client lock, we must be
# responsible for keeping everything alive.
Expand Down Expand Up @@ -617,7 +627,7 @@ def _do_wait_for_a_change(self, finish_time):
return False

def _do_reconnect(self, finish_time):
"""Reconnect after the reconnection delay (or timeout, whichever
""" Reconnect after the reconnection delay (or timeout, whichever
came first).
"""
self._client.close()
Expand All @@ -629,7 +639,7 @@ def _do_reconnect(self, finish_time):
self._reconnect()

def wait_until_ready(self, timeout=None):
"""Block until the job is allocated and ready.
""" Block until the job is allocated and ready.
Parameters
----------
Expand Down Expand Up @@ -676,7 +686,7 @@ def wait_until_ready(self, timeout=None):
raise StateChangeTimeoutError()

def where_is_machine(self, chip_x, chip_y):
"""Locates and returns cabinet, frame, board for a given chip in a\
""" Locates and returns cabinet, frame, board for a given chip in a\
machine allocated to this job.
:param chip_x: chip x location
Expand All @@ -691,19 +701,20 @@ def where_is_machine(self, chip_x, chip_y):


class StateChangeTimeoutError(Exception):
"""Thrown when a state change takes too long to occur."""
""" Thrown when a state change takes too long to occur.
"""


class JobDestroyedError(Exception):
"""Thrown when the job was destroyed while waiting for it to become
ready.
""" Thrown when the job was destroyed while waiting for it to become\
ready.
"""


class _JobStateTuple(namedtuple("_JobStateTuple",
"state,power,keepalive,reason")):
"""Tuple describing the state of a particular job, returned by
:py:meth:`.Job._get_state`.
""" Tuple describing the state of a particular job, returned by\
:py:meth:`.Job._get_state`.
Parameters
----------
Expand All @@ -729,8 +740,8 @@ class _JobStateTuple(namedtuple("_JobStateTuple",
class _JobMachineInfoTuple(namedtuple("_JobMachineInfoTuple",
"width,height,connections,"
"machine_name,boards")):
"""Tuple describing the machine allocated to a job, returned by
:py:meth:`.Job._get_machine_info`.
""" Tuple describing the machine allocated to a job, returned by\
:py:meth:`.Job._get_machine_info`.
Parameters
Expand Down
Loading

0 comments on commit ce3b32d

Please sign in to comment.