Skip to content

Commit

Permalink
Merge pull request #2018 from matthewrmshin/6.11.x-fix-command-polling
Browse files Browse the repository at this point in the history
Restore command polling simple print/write
  • Loading branch information
oliver-sanders committed Oct 11, 2016
2 parents 7d7d6bf + d756687 commit 6dce9df
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 41 deletions.
8 changes: 4 additions & 4 deletions bin/cylc-stop
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,10 @@ from cylc.task_id import TaskID
from cylc.network.suite_command import SuiteCommandClient
from cylc.network.suite_info import SuiteInfoClient
from cylc.option_parsers import CylcOptionParser as COP
from cylc.command_polling import poller
from cylc.command_polling import Poller


class stop_poller(poller):
class StopPoller(Poller):
"""A polling object that checks if a suite has stopped yet."""

def load(self):
Expand Down Expand Up @@ -102,7 +102,7 @@ def main():
help="Shut down after time STOP (ISO 8601 formatted)",
action="store", dest="wall_clock")

stop_poller.add_to_cmd_options(parser, d_max_polls=0)
StopPoller.add_to_cmd_options(parser, d_max_polls=0)
(options, args) = parser.parse_args()
suite = args[0]

Expand All @@ -123,7 +123,7 @@ def main():

if int(options.max_polls) > 0:
# (test to avoid the "nothing to do" warning for # --max-polls=0)
spoller = stop_poller(
spoller = StopPoller(
"suite stopped", options.interval, options.max_polls,
args={
'suite': suite,
Expand Down
8 changes: 4 additions & 4 deletions bin/cylc-suite-state
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,13 @@ from cylc.option_parsers import CylcOptionParser as COP
from cylc.dbstatecheck import (
CylcSuiteDBChecker, DBNotFoundError, DBOperationError)
from cylc.cfgspec.globalcfg import GLOBAL_CFG
from cylc.command_polling import poller
from cylc.command_polling import Poller
from cylc.task_state import TASK_STATUSES_ORDERED

from isodatetime.parsers import TimePointParser, DurationParser


class suite_poller(poller):
class SuitePoller(Poller):
"""A polling object that checks suite state."""

def connect(self):
Expand Down Expand Up @@ -174,7 +174,7 @@ def main():
"check for. " + conds + states,
action="store", dest="status", default=None)

suite_poller.add_to_cmd_options(parser)
SuitePoller.add_to_cmd_options(parser)
(options, args) = parser.parse_args(remove_opts=["--db", "--debug"])

suite = args[0]
Expand Down Expand Up @@ -232,7 +232,7 @@ def main():
os.path.expanduser(
options.run_dir or GLOBAL_CFG.get_host_item('run directory')))

spoller = suite_poller(
spoller = SuitePoller(
"requested state",
options.interval, options.max_polls,
args={'suite': suite,
Expand Down
63 changes: 30 additions & 33 deletions lib/cylc/command_polling.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,19 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""Encapsulates polling activity for CLI commands."""

import sys
from time import sleep, time
from time import sleep

from cylc.suite_logging import OUT, ERR


class poller(object):
class Poller(object):
"""Encapsulates polling activity for cylc commands. Derived classes
must override the check() method to test the polling condition."""

@classmethod
def add_to_cmd_options(cls, parser, d_interval=60, d_max_polls=10):
# add command line options for polling
"""Add command line options for commands that can do polling"""
parser.add_option(
"--max-polls",
help="Maximum number of polls (default " + str(d_max_polls) + ").",
Expand All @@ -47,27 +46,29 @@ def add_to_cmd_options(cls, parser, d_interval=60, d_max_polls=10):
dest="interval",
default=d_interval)

def __init__(self, condition, interval, max_polls, args={}):
def __init__(self, condition, interval, max_polls, args):

self.condition = condition # e.g. "suite stopped"

"""check max_polls is an int"""
# check max_polls is an int
try:
self.max_polls = int(max_polls)
except:
ERR.error("max_polls must be an int")
sys.exit(1)
except ValueError:
sys.exit("max_polls must be an int")

"""check interval is an int"""
# check interval is an int
try:
self.interval = int(interval)
except:
ERR.error("interval must be an integer")
sys.exit(1)
except ValueError:
sys.exit("interval must be an integer")

self.n_polls = 0
self.args = args # any extra parameters needed by check()

def check(self):
"""Abstract method. Test polling condition."""
raise NotImplementedError()

def poll(self):
"""Poll for the condition embodied by self.check().
Return True if condition met, or False if polling exhausted."""
Expand All @@ -76,27 +77,23 @@ def poll(self):
# exit 1 as we can't know if the condition is satisfied
sys.exit("WARNING: nothing to do (--max-polls=0)")
elif self.max_polls == 1:
log_msg = "checking"
sys.stdout.write("checking for '%s'" % self.condition)
else:
log_msg = "polling"
log_msg += " for '" + self.condition + "'"
sys.stdout.write("polling for '%s'" % self.condition)

done = False
while (not done and self.n_polls < self.max_polls):
while self.n_polls < self.max_polls:
self.n_polls += 1
if self.check():
done = True
else:
if self.max_polls > 1:
log_msg += '.'
sleep(self.interval)
if done:
OUT.info(log_msg + ": satisfied")
return True
else:
OUT.info(log_msg)
err_msg = "condition not satisfied",
sys.stdout.write(": satisfied\n")
return True
if self.max_polls > 1:
err_msg += "\nafter " + str(self.max_polls) + " polls"
ERR.error(err_msg)
return False
sys.stdout.write(".")
sleep(self.interval)
sys.stdout.write("\n")
if self.max_polls > 1:
sys.stderr.write(
"ERROR: condition not satisfied after %d polls\n" %
self.max_polls)
else:
sys.stderr.write("ERROR: condition not satisfied\n")
return False

0 comments on commit 6dce9df

Please sign in to comment.