Source code for jsontas.data_structures.wait

# Copyright 2020 Axis Communications AB.
#
# For a full list of individual contributors, please see the commit history.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Wait datastructure."""
import time
from copy import deepcopy
from .datastructure import DataStructure


[docs]class Wait(DataStructure): """Wait datastructure. Wait for a query tree to evaluate to True. Example:: { "$wait": { "for": { "$request": { "url": "http://example.com", "method": "GET" } }, "interval": 1, "timeout": 20, "else": {} } } Request example.com until a non-null response. Maximum 1 request/s for 20s Due to the storage of the 'query_tree' in dataset it is possible to nest queries:: Example:: { "response": { "$from": { "item": { "$wait": { "for": { "$condition": { "then": { "$request": { "url": "http://example.com", "method": "GET" } }, "if": { "key": "$response.status_code", "operator": "$eq", "value": 200 }, "else": null } }, "interval": 1, "timeout": 20, "else": {} } }, "get": "items" } } } Wait for example.com to respond with status_code 200 and a non-null response and get the 'items' key from the response. Maximum 1 request/s for 20s """
[docs] @staticmethod def wait(method, timeout, interval, **kwargs): """Iterate over result from method call. :param method: Method to call. :type method: :meth: :param timeout: How long, in seconds, to iterate. :type timeout: int or None :param interval: How long, in seconds, to wait between method calls. :type interval: int :param kwargs: Keyword arguments to pass to method call. :type kwargs: dict """ end = time.time() + timeout while time.time() < end: try: yield method(**deepcopy(kwargs)) except GeneratorExit: break except: # pylint:disable=bare-except continue time.sleep(interval)
[docs] def execute(self): """Execute wait datastructure. Waiting for will requires a 'query_tree' which is a collection of all requests that are 'below' the 'wait' datastructure. This is to keep track of the queries that have executed before (but not the results of these queries). This query tree is then executed in the :meth:`jsontas.jsontas.JsonTas.resolve` method, which can be considered weird. We're executing JsonTas inside of a JsonTas query. But this is the only way to re-run a query tree. :return: None and the result of re-running a query tree. :rtype: Tuple """ if self.data.get("for"): return None, self.data.get("for") # This is a circular import. # pylint:disable=cyclic-import # pylint:disable=import-outside-toplevel from jsontas.jsontas import JsonTas jsontas = JsonTas(self.dataset) value = None query_tree = self.dataset.get("query_tree") for value in self.wait(jsontas.resolve, self.data.get("timeout"), self.data.get("interval"), json_data=query_tree.get("for")): if value: break return None, value or self.data.get("else")