<commit_before>#pylint: disable=C0301, C0103, W0212

"""
.. module:: radical.pilot.compute_unit
   :platform: Unix
   :synopsis: Implementation of the ComputeUnit class.

.. moduleauthor:: Ole Weidner <ole.weidner@rutgers.edu>
"""

__copyright__ = "Copyright 2013-2014, http://radical.rutgers.edu"
__license__ = "MIT"

import os
import copy
import time

from radical.pilot.utils.logger import logger

from radical.pilot.states import *
from radical.pilot.exceptions import *

from bson import ObjectId
from radical.pilot.db.database import COMMAND_CANCEL_COMPUTE_UNIT

from radical.pilot.staging_directives import TRANSFER

# -----------------------------------------------------------------------------
#
class ComputeUnit(object):
    """A ComputeUnit represent a 'task' that is executed on a ComputePilot.
    ComputeUnits allow to control and query the state of this task.

    .. note:: A ComputeUnit cannot be created directly. The factory method
              :meth:`radical.pilot.UnitManager.submit_units` has to be used instead.

                **Example**::

                      umgr = radical.pilot.UnitManager(session=s)

                      ud = radical.pilot.ComputeUnitDescription()
                      ud.executable = "/bin/date"
                      ud.cores      = 1

                      unit = umgr.submit_units(ud)
    """

    # -------------------------------------------------------------------------
    #
    def __init__(self):
        """ Le constructeur. Not meant to be called directly.
        """
        # 'static' members
        self._uid = None
        self._description = None
        self._manager = None

        # handle to the manager's worker
        self._worker = None

        if os.getenv("RADICAL_PILOT_GCDEBUG", None) is not None:
            logger.debug("GCDEBUG __init__(): ComputeUnit [object id: %s]." % id(self))

    #--------------------------------------------------------------------------
    #
    def __del__(self):
        """Le destructeur.
        """
        if os.getenv("RADICAL_PILOT_GCDEBUG", None) is not None:
            logger.debug("GCDEBUG __del__(): ComputeUnit [object id: %s]." % id(self))

    # -------------------------------------------------------------------------
    #
    @staticmethod
    def _create(unit_manager_obj, unit_description, local_state):
        """ PRIVATE: Create a new compute unit.
        """
        # create and return pilot object
        computeunit = ComputeUnit()

        # Make a copy of the UD to work on without side-effects
        ud_copy = copy.deepcopy(unit_description)
        print 'UD: %s' % unit_description
        print 'Copy of UD: %s' % ud_copy

        if ud_copy.input_staging:
            new_input_staging = []
            for sd in ud_copy.input_staging:
                if isinstance(sd, str):
                    print 'STRING: %s' % sd
                    new_sd = {'source': sd,
                              'target': sd,
                              'action': TRANSFER
                    }
                    logger.debug("Converting string '%s' into dict '%s'" % (sd, new_sd))
                    new_input_staging.append(new_sd)
                elif isinstance(sd, dict):
                    print 'DICT: %s' % sd
                    new_input_staging.append(sd)
                else:
                    print 'UNKNOWN: %s' % sd
            ud_copy.input_staging = new_input_staging

        if ud_copy.output_staging:
            new_output_staging = []
            for sd in ud_copy.output_staging:
                if isinstance(sd, str):
                    print 'STRING: %s' % sd
                    new_sd = {'source': sd,
                              'target': sd,
                              'action': TRANSFER
                    }
                    logger.debug("Converting string '%s' into dict '%s'" % (sd, new_sd))
                    new_output_staging.append(new_sd)
                elif isinstance(sd, dict):
                    print 'DICT: %s' % sd
                    new_output_staging.append(sd)
                else:
                    print 'UNKNOWN: %s' % sd
            ud_copy.output_staging = new_output_staging

        computeunit._description = ud_copy
        #computeunit._description = unit_description
        computeunit._manager     = unit_manager_obj
        computeunit._worker      = unit_manager_obj._worker
        computeunit._uid         = str(ObjectId())
        computeunit._local_state = local_state

        return computeunit

    # -------------------------------------------------------------------------
    #
    @staticmethod
    def _get(unit_manager_obj, unit_ids):
        """ PRIVATE: Get one or more Compute Units via their UIDs.
        """
        units_json = unit_manager_obj._session._dbs.get_compute_units(
            unit_manager_id=unit_manager_obj.uid,
            unit_ids=unit_ids
        )
        # create and return unit objects
        computeunits = []

        for u in units_json:
            computeunit = ComputeUnit()
            computeunit._uid = str(u['_id'])
            computeunit._description = u['description']
            computeunit._manager = unit_manager_obj
            computeunit._worker = unit_manager_obj._worker

            computeunits.append(computeunit)

        return computeunits

    # -------------------------------------------------------------------------
    #
    def as_dict(self):
        """Returns a Python dictionary representation of the object.
        """
        obj_dict = {
            'uid':               self.uid,
            'state':             self.state,
            'exit_code':         self.exit_code,
            'log':               self.log,
            'execution_details': self.execution_details,
            'submission_time':   self.submission_time,
            'working_directory': self.working_directory,
            'start_time':        self.start_time,
            'stop_time':         self.stop_time,
            "FTW_Input_Status":  self.FTunit.FTW_Input_Status,
            "FTW_Input_Directives": unit.FTW_Input_Directives,
            "Agent_Input_Status": unit.Agent_Input_Status,
            "Agent_Input_Directives": unit.Agent_Input_Directives,
            "FTW_Output_Status": unit.FTW_Output_Status,
            "FTW_Output_Directives": unit.FTW_Output_Directives,
            "Agent_Output_Status": unit.Agent_Output_Status,
            "Agent_Output_Directives": unit.Agent_Output_Directives
        }
        return obj_dict

    # -------------------------------------------------------------------------
    #
    def __str__(self):
        """Returns a string representation of the object.
        """
        if not self._uid:
            raise exceptions.IncorrectState("Invalid instance.")

        return str(self.as_dict())

    # -------------------------------------------------------------------------
    #
    @property
    def uid(self):
        """Returns the unit's unique identifier.

        The uid identifies the ComputeUnit within a :class:`UnitManager` and
        can be used to retrieve an existing ComputeUnit.

        **Returns:**
            * A unique identifier (string).
        """
        # uid is static and doesn't change over the lifetime
        # of a unit, hence it can be stored in a member var.
        return self._uid

    # -------------------------------------------------------------------------
    #
    @property
    def working_directory(self):
        """Returns the full working directory URL of this ComputeUnit.
        """
        if not self._uid:
            raise exceptions.IncorrectState("Invalid instance.")

        cu_json = self._worker.get_compute_unit_data(self.uid)
        return cu_json['sandbox']

    # -------------------------------------------------------------------------
    #
    @property
    def stdout(self):
        """Returns a snapshot of the executable's STDOUT stream.

        If this property is queried before the ComputeUnit has reached
        'DONE' or 'FAILED' state it will return None.

        .. warning: This can become very inefficient for lareg data volumes.
        """
        if not self._uid:
            raise exceptions.IncorrectState("Invalid instance.")

        return self._worker.get_compute_unit_stdout(self.uid)

    # -------------------------------------------------------------------------
    #
    @property
    def stderr(self):
        """Returns a snapshot of the executable's STDERR stream.

        If this property is queried before the ComputeUnit has reached
        'DONE' or 'FAILED' state it will return None.

        .. warning: This can become very inefficient for large data volumes.
        """
        if not self._uid:
            raise exceptions.IncorrectState("Invalid instance.")

        return self._worker.get_compute_unit_stderr(self.uid)

    # -------------------------------------------------------------------------
    #
    @property
    def description(self):
        """Returns the ComputeUnitDescription the ComputeUnit was started with.
        """
        # description is static and doesn't change over the lifetime
        # of a unit, hence it is stored as a member var.
        return self._description

    # -------------------------------------------------------------------------
    #
    @property
    def state(self):
        """Returns the current state of the ComputeUnit.
        """
        if not self._uid:
            raise exceptions.IncorrectState(msg="Invalid instance.")

        # try to get state from worker.  If that fails, return local state.
        try :
            cu_json = self._worker.get_compute_unit_data(self.uid)
            return cu_json['state']
        except Exception as e :
            return self._local_state

    # -------------------------------------------------------------------------
    #
    @property
    def state_history(self):
        """Returns the complete state history of the ComputeUnit.
        """
        if not self._uid:
            raise exceptions.IncorrectState(msg="Invalid instance.")

        states = []

        cu_json = self._worker.get_compute_unit_data(self.uid)
        for state in cu_json['statehistory']:
            states.append(State(state=state["state"], timestamp=state["timestamp"]))

        return states

    # -------------------------------------------------------------------------
    #
    @property
    def exit_code(self):
        """Returns the exit code of the ComputeUnit.

        If this property is queried before the ComputeUnit has reached
        'DONE' or 'FAILED' state it will return None.
        """
        if not self._uid:
            raise exceptions.IncorrectState("Invalid instance.")

        cu_json = self._worker.get_compute_unit_data(self.uid)
        return cu_json['exit_code']

    # -------------------------------------------------------------------------
    #
    @property
    def log(self):
        """Returns the logs of the ComputeUnit.
        """
        if not self._uid:
            raise exceptions.IncorrectState("Invalid instance.")

        cu_json = self._worker.get_compute_unit_data(self.uid)
        return cu_json['log']

    # -------------------------------------------------------------------------
    #
    @property
    def execution_details(self):
        """Returns the exeuction location(s) of the ComputeUnit.
        """
        if not self._uid:
            raise exceptions.IncorrectState("Invalid instance.")

        cu_json = self._worker.get_compute_unit_data(self.uid)
        return cu_json

    # -------------------------------------------------------------------------
    #
    @property
    def execution_locations(self):
        """Returns the exeuction location(s) of the ComputeUnit.
           This is just an alias for execution_details.
        """
        return self.execution_details['exec_locs']

    # -------------------------------------------------------------------------
    #
    @property
    def submission_time(self):
        """ Returns the time the ComputeUnit was submitted.
        """
        if not self._uid:
            raise exceptions.IncorrectState("Invalid instance.")

        cu_json = self._worker.get_compute_unit_data(self.uid)
        return cu_json['submitted']

    # -------------------------------------------------------------------------
    #
    @property
    def start_time(self):
        """ Returns the time the ComputeUnit was started on the backend.
        """
        if not self._uid:
            raise exceptions.IncorrectState("Invalid instance.")

        cu_json = self._worker.get_compute_unit_data(self.uid)
        return cu_json['started']

    # -------------------------------------------------------------------------
    #
    @property
    def stop_time(self):
        """ Returns the time the ComputeUnit was stopped.
        """
        if not self._uid:
            raise exceptions.IncorrectState("Invalid instance.")

        cu_json = self._worker.get_compute_unit_data(self.uid)
        return cu_json['finished']

    # -------------------------------------------------------------------------
    #
    def register_callback(self, callback_func):
        """Registers a callback function that is triggered every time the
        ComputeUnit's state changes.

        All callback functions need to have the same signature::

            def callback_func(obj, state)

        where ``object`` is a handle to the object that triggered the callback
        and ``state`` is the new state of that object.
        """
        self._worker.register_unit_callback(self, callback_func)

    # -------------------------------------------------------------------------
    #
    def wait(self, state=[DONE, FAILED, CANCELED],
             timeout=None):
        """Returns when the ComputeUnit reaches a specific state or
        when an optional timeout is reached.

        **Arguments:**

            * **state** [`list of strings`]
              The state(s) that compute unit has to reach in order for the
              call to return.

              By default `wait` waits for the compute unit to reach
              a **terminal** state, which can be one of the following:

              * :data:`radical.pilot.states.DONE`
              * :data:`radical.pilot.states.FAILED`
              * :data:`radical.pilot.states.CANCELED`

            * **timeout** [`float`]
              Optional timeout in seconds before the call returns regardless
              whether the compute unit has reached the desired state or not.
              The default value **None** never times out.

        **Raises:**
        """
        if not self._uid:
            raise exceptions.IncorrectState("Invalid instance.")

        if not isinstance(state, list):
            state = [state]

        start_wait = time.time()
        # the self.state property pulls the state from the back end.
        new_state = self.state
        while new_state not in state:
            time.sleep(1)

            new_state = self.state
            logger.debug(
                "Compute unit %s in state %s" % (self._uid, new_state))

            if(None != timeout) and (timeout <= (time.time() - start_wait)):
                break

        # done waiting -- return the state
        return new_state

    # -------------------------------------------------------------------------
    #
    def cancel(self):
        """Cancel the ComputeUnit.

        **Raises:**

            * :class:`radical.pilot.radical.pilotException`
        """
        # Check if this instance is valid
        if not self._uid:
            raise exceptions.radical.pilotException(
                "Invalid Compute Unit instance.")

        cu_json = self._worker.get_compute_unit_data(self.uid)
        pilot_uid = cu_json['pilot']

        if self.state in [DONE, FAILED, CANCELED]:
            # nothing to do
            logger.debug("Compute unit %s has state %s, can't cancel any longer." % (self._uid, self.state))

        elif self.state in [NEW, PENDING_INPUT_STAGING]:
            logger.debug("Compute unit %s has state %s, going to prevent from starting." % (self._uid, self.state))
            self._manager._session._dbs.set_compute_unit_state(self._uid, CANCELED, ["Received Cancel"])

        elif self.state == STAGING_INPUT:
            logger.debug("Compute unit %s has state %s, will cancel the transfer." % (self._uid, self.state))
            self._manager._session._dbs.set_compute_unit_state(self._uid, CANCELED, ["Received Cancel"])

        elif self.state in [PENDING_EXECUTION, SCHEDULING]:
            logger.debug("Compute unit %s has state %s, will abort start-up." % (self._uid, self.state))
            self._manager._session._dbs.set_compute_unit_state(self._uid, CANCELED, ["Received Cancel"])

        elif self.state == EXECUTING:
            logger.debug("Compute unit %s has state %s, will terminate the task." % (self._uid, self.state))
            self._manager._session._dbs.send_command_to_pilot(cmd=COMMAND_CANCEL_COMPUTE_UNIT, arg=self.uid, pilot_ids=pilot_uid)

        elif self.state == PENDING_OUTPUT_STAGING:
            logger.debug("Compute unit %s has state %s, will abort the transfer." % (self._uid, self.state))
            self._manager._session._dbs.set_compute_unit_state(self._uid, CANCELED, ["Received Cancel"])

        elif self.state == STAGING_OUTPUT:
            logger.debug("Compute unit %s has state %s, will cancel the transfer." % (self._uid, self.state))
            self._manager._session._dbs.set_compute_unit_state(self._uid, CANCELED, ["Received Cancel"])

        else:
            raise exceptions.radical.pilotException(
                "Unknown Compute Unit state: %s, cannot cancel" % self.state)

        # done canceling
        return
<commit_msg>Cleanup.<commit_after>#pylint: disable=C0301, C0103, W0212

"""
.. module:: radical.pilot.compute_unit
   :platform: Unix
   :synopsis: Implementation of the ComputeUnit class.

.. moduleauthor:: Ole Weidner <ole.weidner@rutgers.edu>
"""

__copyright__ = "Copyright 2013-2014, http://radical.rutgers.edu"
__license__ = "MIT"

import os
import copy
import time

from radical.pilot.utils.logger import logger

from radical.pilot.states import *
from radical.pilot.exceptions import *

from bson import ObjectId
from radical.pilot.db.database import COMMAND_CANCEL_COMPUTE_UNIT

from radical.pilot.staging_directives import TRANSFER

# -----------------------------------------------------------------------------
#
class ComputeUnit(object):
    """A ComputeUnit represent a 'task' that is executed on a ComputePilot.
    ComputeUnits allow to control and query the state of this task.

    .. note:: A ComputeUnit cannot be created directly. The factory method
              :meth:`radical.pilot.UnitManager.submit_units` has to be used instead.

                **Example**::

                      umgr = radical.pilot.UnitManager(session=s)

                      ud = radical.pilot.ComputeUnitDescription()
                      ud.executable = "/bin/date"
                      ud.cores      = 1

                      unit = umgr.submit_units(ud)
    """

    # -------------------------------------------------------------------------
    #
    def __init__(self):
        """ Le constructeur. Not meant to be called directly.
        """
        # 'static' members
        self._uid = None
        self._description = None
        self._manager = None

        # handle to the manager's worker
        self._worker = None

        if os.getenv("RADICAL_PILOT_GCDEBUG", None) is not None:
            logger.debug("GCDEBUG __init__(): ComputeUnit [object id: %s]." % id(self))

    #--------------------------------------------------------------------------
    #
    def __del__(self):
        """Le destructeur.
        """
        if os.getenv("RADICAL_PILOT_GCDEBUG", None) is not None:
            logger.debug("GCDEBUG __del__(): ComputeUnit [object id: %s]." % id(self))

    # -------------------------------------------------------------------------
    #
    @staticmethod
    def _create(unit_manager_obj, unit_description, local_state):
        """ PRIVATE: Create a new compute unit.
        """
        # create and return pilot object
        computeunit = ComputeUnit()

        # Make a copy of the UD to work on without side-effects.
        ud_copy = copy.deepcopy(unit_description)

        if ud_copy.input_staging:
            new_input_staging = []
            for sd in ud_copy.input_staging:
                if isinstance(sd, str):
                    print 'STRING: %s' % sd
                    new_sd = {'source': sd,
                              'target': sd,
                              'action': TRANSFER
                    }
                    logger.debug("Converting string '%s' into dict '%s'" % (sd, new_sd))
                    new_input_staging.append(new_sd)
                elif isinstance(sd, dict):
                    print 'DICT: %s' % sd
                    new_input_staging.append(sd)
                else:
                    print 'UNKNOWN: %s' % sd
            ud_copy.input_staging = new_input_staging

        if ud_copy.output_staging:
            new_output_staging = []
            for sd in ud_copy.output_staging:
                if isinstance(sd, str):
                    print 'STRING: %s' % sd
                    new_sd = {'source': sd,
                              'target': sd,
                              'action': TRANSFER
                    }
                    logger.debug("Converting string '%s' into dict '%s'" % (sd, new_sd))
                    new_output_staging.append(new_sd)
                elif isinstance(sd, dict):
                    print 'DICT: %s' % sd
                    new_output_staging.append(sd)
                else:
                    print 'UNKNOWN: %s' % sd
            ud_copy.output_staging = new_output_staging

        computeunit._description = ud_copy
        computeunit._manager     = unit_manager_obj
        computeunit._worker      = unit_manager_obj._worker
        computeunit._uid         = str(ObjectId())
        computeunit._local_state = local_state

        return computeunit

    # -------------------------------------------------------------------------
    #
    @staticmethod
    def _get(unit_manager_obj, unit_ids):
        """ PRIVATE: Get one or more Compute Units via their UIDs.
        """
        units_json = unit_manager_obj._session._dbs.get_compute_units(
            unit_manager_id=unit_manager_obj.uid,
            unit_ids=unit_ids
        )
        # create and return unit objects
        computeunits = []

        for u in units_json:
            computeunit = ComputeUnit()
            computeunit._uid = str(u['_id'])
            computeunit._description = u['description']
            computeunit._manager = unit_manager_obj
            computeunit._worker = unit_manager_obj._worker

            computeunits.append(computeunit)

        return computeunits

    # -------------------------------------------------------------------------
    #
    def as_dict(self):
        """Returns a Python dictionary representation of the object.
        """
        obj_dict = {
            'uid':               self.uid,
            'state':             self.state,
            'exit_code':         self.exit_code,
            'log':               self.log,
            'execution_details': self.execution_details,
            'submission_time':   self.submission_time,
            'working_directory': self.working_directory,
            'start_time':        self.start_time,
            'stop_time':         self.stop_time,
            "FTW_Input_Status":  self.FTunit.FTW_Input_Status,
            "FTW_Input_Directives": unit.FTW_Input_Directives,
            "Agent_Input_Status": unit.Agent_Input_Status,
            "Agent_Input_Directives": unit.Agent_Input_Directives,
            "FTW_Output_Status": unit.FTW_Output_Status,
            "FTW_Output_Directives": unit.FTW_Output_Directives,
            "Agent_Output_Status": unit.Agent_Output_Status,
            "Agent_Output_Directives": unit.Agent_Output_Directives
        }
        return obj_dict

    # -------------------------------------------------------------------------
    #
    def __str__(self):
        """Returns a string representation of the object.
        """
        if not self._uid:
            raise exceptions.IncorrectState("Invalid instance.")

        return str(self.as_dict())

    # -------------------------------------------------------------------------
    #
    @property
    def uid(self):
        """Returns the unit's unique identifier.

        The uid identifies the ComputeUnit within a :class:`UnitManager` and
        can be used to retrieve an existing ComputeUnit.

        **Returns:**
            * A unique identifier (string).
        """
        # uid is static and doesn't change over the lifetime
        # of a unit, hence it can be stored in a member var.
        return self._uid

    # -------------------------------------------------------------------------
    #
    @property
    def working_directory(self):
        """Returns the full working directory URL of this ComputeUnit.
        """
        if not self._uid:
            raise exceptions.IncorrectState("Invalid instance.")

        cu_json = self._worker.get_compute_unit_data(self.uid)
        return cu_json['sandbox']

    # -------------------------------------------------------------------------
    #
    @property
    def stdout(self):
        """Returns a snapshot of the executable's STDOUT stream.

        If this property is queried before the ComputeUnit has reached
        'DONE' or 'FAILED' state it will return None.

        .. warning: This can become very inefficient for lareg data volumes.
        """
        if not self._uid:
            raise exceptions.IncorrectState("Invalid instance.")

        return self._worker.get_compute_unit_stdout(self.uid)

    # -------------------------------------------------------------------------
    #
    @property
    def stderr(self):
        """Returns a snapshot of the executable's STDERR stream.

        If this property is queried before the ComputeUnit has reached
        'DONE' or 'FAILED' state it will return None.

        .. warning: This can become very inefficient for large data volumes.
        """
        if not self._uid:
            raise exceptions.IncorrectState("Invalid instance.")

        return self._worker.get_compute_unit_stderr(self.uid)

    # -------------------------------------------------------------------------
    #
    @property
    def description(self):
        """Returns the ComputeUnitDescription the ComputeUnit was started with.
        """
        # description is static and doesn't change over the lifetime
        # of a unit, hence it is stored as a member var.
        return self._description

    # -------------------------------------------------------------------------
    #
    @property
    def state(self):
        """Returns the current state of the ComputeUnit.
        """
        if not self._uid:
            raise exceptions.IncorrectState(msg="Invalid instance.")

        # try to get state from worker.  If that fails, return local state.
        try :
            cu_json = self._worker.get_compute_unit_data(self.uid)
            return cu_json['state']
        except Exception as e :
            return self._local_state

    # -------------------------------------------------------------------------
    #
    @property
    def state_history(self):
        """Returns the complete state history of the ComputeUnit.
        """
        if not self._uid:
            raise exceptions.IncorrectState(msg="Invalid instance.")

        states = []

        cu_json = self._worker.get_compute_unit_data(self.uid)
        for state in cu_json['statehistory']:
            states.append(State(state=state["state"], timestamp=state["timestamp"]))

        return states

    # -------------------------------------------------------------------------
    #
    @property
    def exit_code(self):
        """Returns the exit code of the ComputeUnit.

        If this property is queried before the ComputeUnit has reached
        'DONE' or 'FAILED' state it will return None.
        """
        if not self._uid:
            raise exceptions.IncorrectState("Invalid instance.")

        cu_json = self._worker.get_compute_unit_data(self.uid)
        return cu_json['exit_code']

    # -------------------------------------------------------------------------
    #
    @property
    def log(self):
        """Returns the logs of the ComputeUnit.
        """
        if not self._uid:
            raise exceptions.IncorrectState("Invalid instance.")

        cu_json = self._worker.get_compute_unit_data(self.uid)
        return cu_json['log']

    # -------------------------------------------------------------------------
    #
    @property
    def execution_details(self):
        """Returns the exeuction location(s) of the ComputeUnit.
        """
        if not self._uid:
            raise exceptions.IncorrectState("Invalid instance.")

        cu_json = self._worker.get_compute_unit_data(self.uid)
        return cu_json

    # -------------------------------------------------------------------------
    #
    @property
    def execution_locations(self):
        """Returns the exeuction location(s) of the ComputeUnit.
           This is just an alias for execution_details.
        """
        return self.execution_details['exec_locs']

    # -------------------------------------------------------------------------
    #
    @property
    def submission_time(self):
        """ Returns the time the ComputeUnit was submitted.
        """
        if not self._uid:
            raise exceptions.IncorrectState("Invalid instance.")

        cu_json = self._worker.get_compute_unit_data(self.uid)
        return cu_json['submitted']

    # -------------------------------------------------------------------------
    #
    @property
    def start_time(self):
        """ Returns the time the ComputeUnit was started on the backend.
        """
        if not self._uid:
            raise exceptions.IncorrectState("Invalid instance.")

        cu_json = self._worker.get_compute_unit_data(self.uid)
        return cu_json['started']

    # -------------------------------------------------------------------------
    #
    @property
    def stop_time(self):
        """ Returns the time the ComputeUnit was stopped.
        """
        if not self._uid:
            raise exceptions.IncorrectState("Invalid instance.")

        cu_json = self._worker.get_compute_unit_data(self.uid)
        return cu_json['finished']

    # -------------------------------------------------------------------------
    #
    def register_callback(self, callback_func):
        """Registers a callback function that is triggered every time the
        ComputeUnit's state changes.

        All callback functions need to have the same signature::

            def callback_func(obj, state)

        where ``object`` is a handle to the object that triggered the callback
        and ``state`` is the new state of that object.
        """
        self._worker.register_unit_callback(self, callback_func)

    # -------------------------------------------------------------------------
    #
    def wait(self, state=[DONE, FAILED, CANCELED],
             timeout=None):
        """Returns when the ComputeUnit reaches a specific state or
        when an optional timeout is reached.

        **Arguments:**

            * **state** [`list of strings`]
              The state(s) that compute unit has to reach in order for the
              call to return.

              By default `wait` waits for the compute unit to reach
              a **terminal** state, which can be one of the following:

              * :data:`radical.pilot.states.DONE`
              * :data:`radical.pilot.states.FAILED`
              * :data:`radical.pilot.states.CANCELED`

            * **timeout** [`float`]
              Optional timeout in seconds before the call returns regardless
              whether the compute unit has reached the desired state or not.
              The default value **None** never times out.

        **Raises:**
        """
        if not self._uid:
            raise exceptions.IncorrectState("Invalid instance.")

        if not isinstance(state, list):
            state = [state]

        start_wait = time.time()
        # the self.state property pulls the state from the back end.
        new_state = self.state
        while new_state not in state:
            time.sleep(1)

            new_state = self.state
            logger.debug(
                "Compute unit %s in state %s" % (self._uid, new_state))

            if(None != timeout) and (timeout <= (time.time() - start_wait)):
                break

        # done waiting -- return the state
        return new_state

    # -------------------------------------------------------------------------
    #
    def cancel(self):
        """Cancel the ComputeUnit.

        **Raises:**

            * :class:`radical.pilot.radical.pilotException`
        """
        # Check if this instance is valid
        if not self._uid:
            raise exceptions.radical.pilotException(
                "Invalid Compute Unit instance.")

        cu_json = self._worker.get_compute_unit_data(self.uid)
        pilot_uid = cu_json['pilot']

        if self.state in [DONE, FAILED, CANCELED]:
            # nothing to do
            logger.debug("Compute unit %s has state %s, can't cancel any longer." % (self._uid, self.state))

        elif self.state in [NEW, PENDING_INPUT_STAGING]:
            logger.debug("Compute unit %s has state %s, going to prevent from starting." % (self._uid, self.state))
            self._manager._session._dbs.set_compute_unit_state(self._uid, CANCELED, ["Received Cancel"])

        elif self.state == STAGING_INPUT:
            logger.debug("Compute unit %s has state %s, will cancel the transfer." % (self._uid, self.state))
            self._manager._session._dbs.set_compute_unit_state(self._uid, CANCELED, ["Received Cancel"])

        elif self.state in [PENDING_EXECUTION, SCHEDULING]:
            logger.debug("Compute unit %s has state %s, will abort start-up." % (self._uid, self.state))
            self._manager._session._dbs.set_compute_unit_state(self._uid, CANCELED, ["Received Cancel"])

        elif self.state == EXECUTING:
            logger.debug("Compute unit %s has state %s, will terminate the task." % (self._uid, self.state))
            self._manager._session._dbs.send_command_to_pilot(cmd=COMMAND_CANCEL_COMPUTE_UNIT, arg=self.uid, pilot_ids=pilot_uid)

        elif self.state == PENDING_OUTPUT_STAGING:
            logger.debug("Compute unit %s has state %s, will abort the transfer." % (self._uid, self.state))
            self._manager._session._dbs.set_compute_unit_state(self._uid, CANCELED, ["Received Cancel"])

        elif self.state == STAGING_OUTPUT:
            logger.debug("Compute unit %s has state %s, will cancel the transfer." % (self._uid, self.state))
            self._manager._session._dbs.set_compute_unit_state(self._uid, CANCELED, ["Received Cancel"])

        else:
            raise exceptions.radical.pilotException(
                "Unknown Compute Unit state: %s, cannot cancel" % self.state)

        # done canceling
        return
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
# flake8: noqa

import account_sepa_purpose
import account_sdd_mandate
import account_voucher
import sepa_batch
import res_bank
<commit_msg>TASK-457 Added new overloaded model to '__init__.py'<commit_after># -*- coding: utf-8 -*-
# flake8: noqa

import account_sepa_purpose
import account_sdd_mandate
import account_voucher
import sepa_batch
import res_bank
import res_partner_bank
<|endoftext|>


<commit_before>import tkinter as tk

class Header(tk.Frame):
    """ Default header with breadcrumb bar, title, and instruction text """
    def __init__(self, parent, title, instruction):
        tk.Frame.__init__(self, parent, bg="white")
        self.parent = parent

        # breadcrumb
        tk.Frame(self, bg="orange", height=30).pack(fill="x")

        # title and text
        tk.Label(self, text=title).pack(expand=1)
        tk.Label(self, wraplength=700, text=instruction).pack(expand=1)

class NavButton(tk.Button):
    """ Standard layout for 'previous'- & 'next'-button """
    def __init__(self, parent, color, line):
        tk.Button.__init__(self, parent, bg=color, text=line)
        self.parent = parent

class Footer(tk.Frame):
    """ Default footer containing a 'previous'- and a 'next'-button """
    def __init__(self, parent):
        tk.Frame.__init__(self, parent, bg="gray", height=200)
        self.parent = parent

        NavButton(self, color="white", line="PREVIOUS").pack(side="left")
        NavButton(self, color="pink", line="NEXT").pack(side="right")

class Headline(tk.Label):
    """ Default headline style (NOT title style!) """
    def __init__(self, parent, line):
        tk.Label.__init__(self, parent, text=line, bg="aqua")
        self.parent = parent

class ToggleButton(tk.Button):
    """ Default style for buttons without borders / selectable text """
    def __init__(self, parent, line):
        tk.Button.__init__(self, parent, text=line)
        self.parent = parent

class InputField(tk.Frame):
    """ Default style for input fields with description """
    def __init__(self, parent, line):
        tk.Frame.__init__(self, parent, bg="white", width=200, height=150)
        self.parent = parent

        tk.Label(self, text=line).pack()
        tk.Entry(self).pack()

class Races(tk.Frame):
    """ Main race selection frame (IIa) """
    def __init__(self, parent):
        tk.Frame.__init__(self, parent, bg="red")
        self.parent = parent

        # initialize content
        Headline(self, line="Human").grid(row=0, column=0)
        ToggleButton(self, line="Breton").grid(row=1, column=0)
        ToggleButton(self, line="Nord").grid(row=2, column=0)
        ToggleButton(self, line="Imperial").grid(row=3, column=0)
        ToggleButton(self, line="Redguard").grid(row=4, column=0)

        Headline(self, line="Mer").grid(row=0, column=1)
        ToggleButton(self, line="Altmer").grid(row=1, column=1)
        ToggleButton(self, line="Bosmer").grid(row=2, column=1)
        ToggleButton(self, line="Dunmer").grid(row=3, column=1)
        ToggleButton(self, line="Orc").grid(row=4, column=1)

        Headline(self, line="Beast").grid(row=0, column=2)
        ToggleButton(self, line="Argonian").grid(row=1, column=2)
        ToggleButton(self, line="Khajiit").grid(row=2, column=2)

class LevelFields(tk.Frame):
    """ Frame where current and goal level are entered (IIb) """
    def __init__(self, parent):
        tk.Frame.__init__(self, parent, bg="red")
        self.parent = parent

        center = tk.Frame(self, bg="aqua")
        center.pack(expand=1)

        InputField(center, "Your Level:").pack(side="left")
        InputField(center, "Your Goal:").pack(side="left")

class GoalLevelField(tk.Frame):
    """ Frame where goal level is entered (IVa) """
    def __init__(self, parent):
        tk.Frame.__init__(self, parent, bg="red")
        self.parent = parent

        InputField(self, "Your Goal:").pack()

class Skills(tk.Frame):
    """ Main skill selection frame (III) """
    def __init__(self, parent):
        tk.Frame.__init__(self, parent, bg="green")
        self.parent = parent

        # initialize content
        Headline(self, line="Magic").grid(row=0, column=0)
        ToggleButton(self, line="Illusion").grid(row=1, column=0)
        ToggleButton(self, line="Conjuration").grid(row=2, column=0)
        ToggleButton(self, line="Destruction").grid(row=3, column=0)
        ToggleButton(self, line="Restoration").grid(row=4, column=0)
        ToggleButton(self, line="Alteration").grid(row=5, column=0)
        ToggleButton(self, line="Enchanting").grid(row=6, column=0)

        Headline(self, line="Combat").grid(row=0, column=1)
        ToggleButton(self, line="Smithing").grid(row=1, column=1)
        ToggleButton(self, line="Heavy Armor").grid(row=2, column=1)
        ToggleButton(self, line="Block").grid(row=3, column=1)
        ToggleButton(self, line="Two-handed").grid(row=4, column=1)
        ToggleButton(self, line="One-handed").grid(row=5, column=1)
        ToggleButton(self, line="Archery").grid(row=6, column=1)

        Headline(self, line="Stealth").grid(row=0, column=2)
        ToggleButton(self, line="Light Armor").grid(row=1, column=2)
        ToggleButton(self, line="Sneak").grid(row=2, column=2)
        ToggleButton(self, line="Lockpicking").grid(row=3, column=2)
        ToggleButton(self, line="Pickpocket").grid(row=4, column=2)
        ToggleButton(self, line="Speech").grid(row=5, column=2)
        ToggleButton(self, line="Alchemy").grid(row=6, column=2)

class ContentWrapper(tk.Frame):
    def __init__(self, parent):
        tk.Frame.__init__(self, parent, bg="blue")
        self.parent = parent

        Header(self, "Title", "At vero eos et accusam et justo duo dolores et ea rebum.").pack(fill="x")
        GoalLevelField(self).pack(fill="x")
        Footer(self).pack(fill="x", side="bottom")

class Start(tk.Frame):
    def __init__(self, parent):
        tk.Frame.__init__(self, parent, bg="white")
        self.parent = parent

        # initialize content
        __image = tk.Frame(self, bg="gray", width=150, height=150)
        __title = tk.Label(self, bg="white", text="Welcome!")
        __introduction = tk.Label(self, bg="white", wraplength=700,
            text="Lorem ipsum dolor sit amet, consetetur sadipscing elitr, "
                 "sed diam nonumy eirmod tempor invidunt ut labore et dolore "
                 "magna aliquyam erat, sed diam voluptua.")
        __wrapper = tk.Frame(self, bg="red", width=300, height=100)
        __new = tk.Button(__wrapper, text="NEW")
        __existing = tk.Button(__wrapper, text="EXISTING")

        __image.pack(expand=1)
        __title.pack(expand=1)
        __introduction.pack(expand=1)
        __wrapper.pack(expand=1)
        __new.pack(side="left")
        __existing.pack(side="right")

def configure_window(self):
    # title
    self.title("Skyrim Calculator")

    # size
    width = 800
    height = 600
    self.minsize(width, height)

    # position
    x_pos = (self.winfo_screenwidth() - width) / 2
    y_pos = (self.winfo_screenheight() - height) / 2
    self.geometry("%dx%d+%d+%d" % (width, height, x_pos, y_pos))

if __name__ == "__main__":
    root = tk.Tk()
    configure_window(root)
    start = ContentWrapper(root).pack(fill="both", expand=1)
    root.mainloop()
<commit_msg>skill level entry<commit_after>import tkinter as tk

class Header(tk.Frame):
    """ Default header with breadcrumb bar, title, and instruction text """
    def __init__(self, parent, title, instruction):
        tk.Frame.__init__(self, parent, bg="white")
        self.parent = parent

        # breadcrumb
        tk.Frame(self, bg="orange", height=30).pack(fill="x")

        # title and text
        tk.Label(self, text=title).pack(expand=1)
        tk.Label(self, wraplength=700, text=instruction).pack(expand=1)

class NavButton(tk.Button):
    """ Standard layout for 'previous'- & 'next'-button """
    def __init__(self, parent, color, label):
        tk.Button.__init__(self, parent, bg=color, text=label)
        self.parent = parent

class Footer(tk.Frame):
    """ Default footer containing a 'previous'- and a 'next'-button """
    def __init__(self, parent):
        tk.Frame.__init__(self, parent, bg="gray", height=200)
        self.parent = parent

        NavButton(self, "white", "PREVIOUS").pack(side="left")
        NavButton(self, color="pink", label="NEXT").pack(side="right")

class Headline(tk.Label):
    """ Default headline style (NOT title style!) """
    def __init__(self, parent, line):
        tk.Label.__init__(self, parent, text=line, bg="aqua")
        self.parent = parent

class ToggleButton(tk.Button):
    """ Default style for buttons without borders / selectable text """
    def __init__(self, parent, label):
        tk.Button.__init__(self, parent, text=label)
        self.parent = parent

class BigField(tk.Frame):
    """ Default style for character level input fields with description """
    def __init__(self, parent, label):
        tk.Frame.__init__(self, parent, bg="white", width=200, height=150)
        self.parent = parent

        tk.Label(self, text=label).pack()
        tk.Entry(self).pack()

class SmallField(tk.Frame):
    """ Default style for skill level input fields with description """
    def __init__(self, parent, label):
        tk.Frame.__init__(self, parent)
        self.parent = parent

        tk.Label(self, text=label).pack(side="left")
        tk.Entry(self).pack(side="left")

class Races(tk.Frame):
    """ Main race selection frame (IIa) """
    def __init__(self, parent):
        tk.Frame.__init__(self, parent, bg="red")
        self.parent = parent

        # initialize content
        Headline(self, line="Human").grid(row=0, column=0)
        ToggleButton(self, label="Breton").grid(row=1, column=0)
        ToggleButton(self, label="Nord").grid(row=2, column=0)
        ToggleButton(self, label="Imperial").grid(row=3, column=0)
        ToggleButton(self, label="Redguard").grid(row=4, column=0)

        Headline(self, line="Mer").grid(row=0, column=1)
        ToggleButton(self, label="Altmer").grid(row=1, column=1)
        ToggleButton(self, label="Bosmer").grid(row=2, column=1)
        ToggleButton(self, label="Dunmer").grid(row=3, column=1)
        ToggleButton(self, label="Orc").grid(row=4, column=1)

        Headline(self, line="Beast").grid(row=0, column=2)
        ToggleButton(self, label="Argonian").grid(row=1, column=2)
        ToggleButton(self, label="Khajiit").grid(row=2, column=2)

class CharLevelSelection(tk.Frame):
    """ Frame where current and goal level are entered (IIb) """
    def __init__(self, parent):
        tk.Frame.__init__(self, parent, bg="red")
        self.parent = parent

        center = tk.Frame(self, bg="aqua")
        center.pack(expand=1)
        BigField(center, label="Your Level:").pack(side="left")
        BigField(center, label="Your Goal:").pack(side="left")

class Skills(tk.Frame):
    """ Main skill selection frame (III) """
    def __init__(self, parent):
        tk.Frame.__init__(self, parent, bg="green")
        self.parent = parent

        # initialize content
        Headline(self, line="Magic").grid(row=0, column=0)
        ToggleButton(self, label="Illusion").grid(row=1, column=0)
        ToggleButton(self, label="Conjuration").grid(row=2, column=0)
        ToggleButton(self, label="Destruction").grid(row=3, column=0)
        ToggleButton(self, label="Restoration").grid(row=4, column=0)
        ToggleButton(self, label="Alteration").grid(row=5, column=0)
        ToggleButton(self, label="Enchanting").grid(row=6, column=0)

        Headline(self, line="Combat").grid(row=0, column=1)
        ToggleButton(self, label="Smithing").grid(row=1, column=1)
        ToggleButton(self, label="Heavy Armor").grid(row=2, column=1)
        ToggleButton(self, label="Block").grid(row=3, column=1)
        ToggleButton(self, label="Two-handed").grid(row=4, column=1)
        ToggleButton(self, label="One-handed").grid(row=5, column=1)
        ToggleButton(self, label="Archery").grid(row=6, column=1)

        Headline(self, line="Stealth").grid(row=0, column=2)
        ToggleButton(self, label="Light Armor").grid(row=1, column=2)
        ToggleButton(self, label="Sneak").grid(row=2, column=2)
        ToggleButton(self, label="Lockpicking").grid(row=3, column=2)
        ToggleButton(self, label="Pickpocket").grid(row=4, column=2)
        ToggleButton(self, label="Speech").grid(row=5, column=2)
        ToggleButton(self, label="Alchemy").grid(row=6, column=2)

class GoalLevelSelection(tk.Frame):
    """ Frame where goal level is entered (IVa) """
    def __init__(self, parent):
        tk.Frame.__init__(self, parent, bg="red")
        self.parent = parent

        BigField(self, label="Your Goal:").pack()

class SkillLevelSelection(tk.Frame):
    """ Frame where skill levels can be entered (IVb) """
    def __init__(self, parent):
        tk.Frame.__init__(self, parent, bg="red")
        self.parent = parent

        # dummy data
        SmallField(self, label="Alchemy").pack()
        SmallField(self, label="Destruction").pack()

class ContentWrapper(tk.Frame):
    """ Contains all necessary parts of a view """
    def __init__(self, parent):
        tk.Frame.__init__(self, parent, bg="blue")
        self.parent = parent

        Header(self, "Title", "At vero eos et accusam et justo duo dolores et ea rebum.").pack(fill="x")
        SkillLevelSelection(self).pack(fill="x")
        Footer(self).pack(fill="x", side="bottom")

class Start(tk.Frame):
    def __init__(self, parent):
        tk.Frame.__init__(self, parent, bg="white")
        self.parent = parent

        # initialize content
        __image = tk.Frame(self, bg="gray", width=150, height=150)
        __title = tk.Label(self, bg="white", text="Welcome!")
        __introduction = tk.Label(self, bg="white", wraplength=700,
            text="Lorem ipsum dolor sit amet, consetetur sadipscing elitr, "
                 "sed diam nonumy eirmod tempor invidunt ut labore et dolore "
                 "magna aliquyam erat, sed diam voluptua.")
        __wrapper = tk.Frame(self, bg="red", width=300, height=100)
        __new = tk.Button(__wrapper, text="NEW")
        __existing = tk.Button(__wrapper, text="EXISTING")

        __image.pack(expand=1)
        __title.pack(expand=1)
        __introduction.pack(expand=1)
        __wrapper.pack(expand=1)
        __new.pack(side="left")
        __existing.pack(side="right")

def configure_window(self):
    # title
    self.title("Skyrim Calculator")

    # size
    width = 800
    height = 600
    self.minsize(width, height)

    # position
    x_pos = (self.winfo_screenwidth() - width) / 2
    y_pos = (self.winfo_screenheight() - height) / 2
    self.geometry("%dx%d+%d+%d" % (width, height, x_pos, y_pos))

if __name__ == "__main__":
    root = tk.Tk()
    configure_window(root)
    start = ContentWrapper(root).pack(fill="both", expand=1)
    root.mainloop()
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-

from django.views.decorators.csrf import csrf_exempt
from django.http import HttpResponse
from django.http import HttpResponseRedirect
from django.template import Context, loader
from django.utils import simplejson as json
from django.core.mail import send_mail

import rsdbapi as rsdb
import csv, codecs, cStringIO
import re
from time import time

from StringIO import StringIO
from zipfile import ZipFile

# to be removed soon
def choose_collection( data ):
    # getting data from db using col_nr
    return_data = get_perspectives( data['col_nr'] )
    json_data = json.dumps( return_data )
    return HttpResponse( json_data )

# get the basic, top-level view of some issue
def get_init_data( data ):
    db= rsdb.DBconnect("mongodb").dbconnect
    coll= rsdb.Collection(query= { 'level': 'a' })

    return_data = {}
    return_data['rows']= coll.get_data(
        db, data['dataset'], data['perspective'], data['issue']
        )
    return_data['perspective']= coll.metadata_complete

    json_data = json.dumps( return_data )

    return HttpResponse( json_data )

# get the subtree of the next level
def get_node( data ):
    db= rsdb.DBconnect("mongodb").dbconnect
    coll= rsdb.Collection(query= { 'parent': data['parent'] })

    return_data= coll.get_data(
        db, data['dataset'], data['perspective'], data['issue']
        )

    json_data = json.dumps( return_data )

    return HttpResponse(json_data)

def build_regexp(searchline, strictsearch):
    """ construct regexp for search """
    # building regexp for search
    if strictsearch:
        # ver 0.0
        # searchline= "^%(lookupstr)s\s|\s%(lookupstr)s\s|\s%(lookupstr)s$" % { "lookupstr": searchline }
        # ver 0.1
        searchline= "^%(lookupstr)s([^a-z][^A-Z][^0-9]|\s)|([^a-z][^A-Z][^0-9]|\s)%(lookupstr)s([^a-z][^A-Z][^0-9]|\s)|([^a-z][^A-Z][^0-9]|\s)%(lookupstr)s$" % { "lookupstr": searchline }

    return searchline

def do_search(scope_list, regx, dbconn):
    """
    TO-DO:
    - search with automatic substitution of specific polish letters
      (lowercase & uppercase): user can enter 'lodz', but the search
      should find 'Łódż'
    - search with flexible processing of prefixes and suffixes
      (see str.endswith and startswith)
    - search in 'info' keys
    """
    ns_list= [] # list of results
    stat_dict= { "errors": [] }
    found_num= 0 # number of records found
    exclude_fields= ['idef', 'idef_sort', 'parent', 'parent_sort', 'level'] # not all fields are searchable

    for sc in scope_list: # fill the list of collections
        sc_list= sc.split('-')
        dataset, idef, issue= int(sc_list[0]), int(sc_list[1]), str(sc_list[2])
        coll= rsdb.Collection(fields=["perspective", "ns", "columns"])
        metadata= coll.get_complete_metadata(dataset, idef, issue, dbconn)
        if metadata is None:
            stat_dict['errors'].append('collection not found %s' % sc)
        else:
            curr_coll_dict= {
                'perspective': metadata['perspective'],
                'dataset': dataset,
                'view': idef,
                'issue': issue,
                'data': []
                }

            coll.set_fields(None) # for search we need all fields, except for exclude_fields
            for fld in metadata['columns']:
                if 'processable' in fld:
                    check_str= fld['type'] == 'string'
                    check_excl= fld['key'] not in exclude_fields
                    if fld['processable'] and check_str and check_excl:
                        search_query= { fld['key']: regx }
                        coll.set_query(search_query)
                        found= coll.get_data(dbconn, dataset, idef, issue)
                        if len(found) > 0:
                            for found_elt in found:
                                curr_coll_dict['data'].append({
                                    'key': fld['key'],
                                    'text': found_elt[str(fld['key'])],
                                    'idef': found_elt['idef'],
                                    'parent': found_elt['parent']
                                    })
                                found_num += 1
            if len(curr_coll_dict['data']) > 0:
                ns_list.append(curr_coll_dict)

    stat_dict.update( { 'records_found': found_num } )

    return { 'stat': stat_dict, 'result': ns_list }

def search_data( request ):
    """
    search engine enter point
    """
    usrqry = request.GET.get( 'query', '' )
    scope = request.GET.get( 'scope', '' )
    strict = request.GET.get( 'strict', 'false' )
    # converting scope and strict to objects
    scope_list= scope.split(',')
    if strict == 'false':
        strict= False
    else:
        strict= True
    # cleaning user query
    usrqry= usrqry.strip()
    usrqry= re.sub('\s+', ' ', usrqry) # cleaning multiple spaces

    lookup= build_regexp(usrqry, strict)
    regx= re.compile(lookup, re.IGNORECASE)

    result= { }
    total_rec= 0

    db= rsdb.DBconnect('mongodb').dbconnect

    # 1st PASS
    tl1= time() # starting to search
    result_1= do_search(scope_list, regx, db)
    total_rec += result_1['stat']['records_found']
    tlap1= time()-tl1 # 1st pass finished
    result_1['stat'].update( { "search_time": "%0.6f" % tlap1 } )
    result['strict']= result_1

    # 2nd PASS
    second_pass_list= []
    if not strict: # second pass makes sense
        second_pass_list= usrqry.split(' ')

        result_2= { 'stat': { 'records_found': 0 }, 'result': [] } # blank dict for 2nd pass
        if len(second_pass_list) > 0:
            tl2= time() # starting to search

            for wrd in second_pass_list:
                lookup= build_regexp(wrd, True) # we look for separate words using strict
                regx= re.compile(lookup, re.IGNORECASE)
                result_2_curr= do_search(scope_list, regx, db)

                if result_2_curr['stat']['records_found'] > 0:
                    result_2['result'].append( result_2_curr['result'] )
                    result_2['stat']['records_found'] += result_2_curr['stat']['records_found']

                total_rec += result_2_curr['stat']['records_found']
                tlap2= time()-tl2 # 2nd pass finished
                result_2['stat'].update( { "search_time": "%0.6f" % tlap2 } )

            result['loose']= result_2

    tlap= time()-tl1
    result.update( {
        "search_time_total": "%0.6f" % tlap,
        'records_found_total': total_rec
        } )

    return HttpResponse( json.dumps( result ))

def string2list( in_str ):
    """ converts comma separated string to the list """
    out_list= []
    try:
        for elm in in_str.split(','):
            if '[' in elm:
                elm= elm.replace('[', '')
            if ']' in elm:
                elm= elm.replace(']', '')
            out_list.append( elm.strip().encode('utf-8') )
    except:
        pass

    return out_list

def build_idef_regexp( curr_idef ):
    """ build regexp quering collection """
    level_num= curr_idef.count('-')
    if level_num > 0: # deeper than 'a'
        idef_srch= curr_idef.rsplit('-', 1)[0]
        lookup_idef= "^%s\-\d+$" % idef_srch
        curr_idef= idef_srch
        level= 1
        while level < level_num:
            idef_srch= curr_idef.rsplit('-', 1)[0]
            lookup_idef += "|^%s\-\d+$" % idef_srch
            curr_idef= idef_srch
            level += 1
        lookup_idef += "|^([A-Z]|\d)+$"
    else: # just query the highest level
        lookup_idef= "^([A-Z]|\d)+$"

    return lookup_idef

def build_query( idef_list ):
    lookup, i= "", 0
    for idef in idef_list:
        i += 1
        lookup_idef= build_idef_regexp( idef )

        lookup += "(%s)|" % lookup_idef
        if i == len(idef_list):
            lookup= lookup[:-1] # cutting the last symbol | in case it's the end of list

    if len(idef_list) == 1: # single idef
        lookup= lookup[1:-1] # cutting ( and )

    return lookup

# get initial_data + subtrees to searched nodes
def get_searched_data( request ):
    response_dict = {
        'dataset': int( request.GET.get( 'dataset', -1 ) ),
        'view': int( request.GET.get( 'view', -1 ) ),
        'issue': request.GET.get( 'issue', '' ).encode('utf-8'),
        'idef': string2list( request.POST.get( 'idef', '' ) ),
        'regexp': True
    }

    find_query= build_query( response_dict['idef'] )
    # regexpquery= re.compile(find_query, re.IGNORECASE)

    db= rsdb.DBconnect("mongodb").dbconnect
    coll= rsdb.Collection(query= { 'idef': { '$regex': find_query} })

    return_data = {}
    return_data['rows']= coll.get_data(
        db, response_dict['dataset'], response_dict['view'], response_dict['issue']
        )
    return_data['perspective']= coll.metadata_complete

    if 'query' in return_data['perspective']: # not json serializable
        try:
            sr= json.dumps( return_data['perspective']['query'] )
        except: # not json serializable!
            if 'idef' in return_data['perspective']['query']:
                return_data['perspective']['query']['idef']= find_query # re-write it with plain regexp
        del return_data['perspective']['query']

    return HttpResponse( json.dumps(return_data) )

# store front-end state as a permalink in mongo
@csrf_exempt
def store_state( request ):
    data = request.GET.get( 'state', '' )
    #
    # store in mongo, create uniq idef and send it back to front-end
    #

    return HttpResponse( json.dumps({'id': '1000'}) ) #replace '1000' with uniq idef

# init application prepared to handle restore data
def init_restore( request, idef ):
    template = loader.get_template( "restore.html" )
    context = Context({
        'meta': get_ms_nav(),
        'idef': idef
    })
    return HttpResponse( template.render( context ))

#restore front-end state from mongo
def restore_state( request ):
    idef = request.GET.get( 'idef', '-1' )
    data = 'get_me_from_mongo_my_name_is_' + idef

    return HttpResponse( data )

# list of possible ajax calls
func_dict = {
    # get a list of perspectives after choosing a certain collection
    "choose_collection": choose_collection,

    # get data from DB when the first time a perspective is chosen
    "get_init_data": get_init_data,

    # get a sub-level data from DB
    "get_node": get_node,

    # to be implemented
    }

def get_page( data ):
    template = loader.get_template( "test.html" )
#     context = Context( tmp_solution_for_metadata() )
    context = Context( get_ms_nav() )
    return HttpResponse( template.render( context ))

def app_page( request ):
    data = request.GET
    if data == {}:
        return get_page( request )
    else:
        function_id = data['action']
        return func_dict[function_id]( data )

def redirect( request ):
    return HttpResponseRedirect('/app')

@csrf_exempt
def feedback_email( request ):
    from_email = request.POST.get( 'email', 'NO EMAIL PROVIDED' )
    message = request.POST.get( 'message', 'MESSAGE LEFT EMPTY' )

    send_mail( 'Raw Salad Feedback',
                message,
                from_email,
                ['ktrzewiczek@centrumcyfrowe.pl'] )

    return HttpResponse( 'Email sent' )

@csrf_exempt
def download_data( request ):
    response = HttpResponse()
    files = request.POST.get( 'csv_string' ).split( '--file--' )[:-1]

    # send one sheet as CSV and collection of sheets as ZIP
    if len( files ) == 1:
        f = files[0]
        response['Content-Type'] = 'text/csv'
        response['Content-Disposition'] = 'attachment; filename=data.csv'

        if '.csv' in f:
            response.write( open( 'site_media/csv/' + f ).read() )
        else:
            data = f.split( '|' )[:-1]

            writer = UnicodeWriter( response )
            for row in data:
                writer.writerow( row.split(';') )

    else:
        in_memory = StringIO()
        zip = ZipFile( in_memory, 'a' )

        for i, f in enumerate( files ):
            if '.csv' in f:
                csv_string = open( 'site_media/csv/' + f ).read()
            else:
                csv_string = f.replace( '|', '\n' ).encode( 'utf-8' )

            zip.writestr( 'data-'+str(i)+'.csv', csv_string )

        # fix for Linux zip files read in Windows
        for file in zip.filelist:
            file.create_system = 0

        zip.close()

        response['Content-Type'] = 'application/zip'
        response['Content-Disposition'] = "attachment; filename=collected_data.zip"

        in_memory.seek( 0 )
        response.write( in_memory.read() )

    return response

def get_ms_nav():
    db= rsdb.DBconnect("mongodb").dbconnect
    nav_full= rsdb.Navtree().get_nav_full(db)
    out= { 'meta_data': json.dumps( nav_full ) }
    return out

class UnicodeWriter:
    """
    A CSV writer which will write rows to CSV file "f",
    which is encoded in the given encoding.
    """

    def __init__(self, f, dialect=csv.excel, encoding="utf-8", **kwds):
        # Redirect output to a queue
        self.queue = cStringIO.StringIO()
        self.writer = csv.writer(self.queue, dialect=dialect, delimiter=';', **kwds)
        self.stream = f
        self.encoder = codecs.getincrementalencoder(encoding)()

    def writerow(self, row):
        self.writer.writerow([s.encode("utf-8") for s in row])
        # Fetch UTF-8 output from the queue ...
        data = self.queue.getvalue()
        data = data.decode("utf-8")
        # ... and reencode it into the target encoding
        data = self.encoder.encode(data)
        # write to the target stream
        self.stream.write(data)
        # empty queue
        self.queue.truncate(0)

    def writerows(self, rows):
        for row in rows:
            self.writerow(row)
<commit_msg>POST to GET in search<commit_after># -*- coding: utf-8 -*-

from django.views.decorators.csrf import csrf_exempt
from django.http import HttpResponse
from django.http import HttpResponseRedirect
from django.template import Context, loader
from django.utils import simplejson as json
from django.core.mail import send_mail

import rsdbapi as rsdb
import csv, codecs, cStringIO
import re
from time import time

from StringIO import StringIO
from zipfile import ZipFile

# to be removed soon
def choose_collection( data ):
    # getting data from db using col_nr
    return_data = get_perspectives( data['col_nr'] )
    json_data = json.dumps( return_data )
    return HttpResponse( json_data )

# get the basic, top-level view of some issue
def get_init_data( data ):
    db= rsdb.DBconnect("mongodb").dbconnect
    coll= rsdb.Collection(query= { 'level': 'a' })

    return_data = {}
    return_data['rows']= coll.get_data(
        db, data['dataset'], data['perspective'], data['issue']
        )
    return_data['perspective']= coll.metadata_complete

    json_data = json.dumps( return_data )

    return HttpResponse( json_data )

# get the subtree of the next level
def get_node( data ):
    db= rsdb.DBconnect("mongodb").dbconnect
    coll= rsdb.Collection(query= { 'parent': data['parent'] })

    return_data= coll.get_data(
        db, data['dataset'], data['perspective'], data['issue']
        )

    json_data = json.dumps( return_data )

    return HttpResponse(json_data)

def build_regexp(searchline, strictsearch):
    """ construct regexp for search """
    # building regexp for search
    if strictsearch:
        # ver 0.0
        # searchline= "^%(lookupstr)s\s|\s%(lookupstr)s\s|\s%(lookupstr)s$" % { "lookupstr": searchline }
        # ver 0.1
        searchline= "^%(lookupstr)s([^a-z][^A-Z][^0-9]|\s)|([^a-z][^A-Z][^0-9]|\s)%(lookupstr)s([^a-z][^A-Z][^0-9]|\s)|([^a-z][^A-Z][^0-9]|\s)%(lookupstr)s$" % { "lookupstr": searchline }

    return searchline

def do_search(scope_list, regx, dbconn):
    """
    TO-DO:
    - search with automatic substitution of specific polish letters
      (lowercase & uppercase): user can enter 'lodz', but the search
      should find 'Łódż'
    - search with flexible processing of prefixes and suffixes
      (see str.endswith and startswith)
    - search in 'info' keys
    """
    ns_list= [] # list of results
    stat_dict= { "errors": [] }
    found_num= 0 # number of records found
    exclude_fields= ['idef', 'idef_sort', 'parent', 'parent_sort', 'level'] # not all fields are searchable

    for sc in scope_list: # fill the list of collections
        sc_list= sc.split('-')
        dataset, idef, issue= int(sc_list[0]), int(sc_list[1]), str(sc_list[2])
        coll= rsdb.Collection(fields=["perspective", "ns", "columns"])
        metadata= coll.get_complete_metadata(dataset, idef, issue, dbconn)
        if metadata is None:
            stat_dict['errors'].append('collection not found %s' % sc)
        else:
            curr_coll_dict= {
                'perspective': metadata['perspective'],
                'dataset': dataset,
                'view': idef,
                'issue': issue,
                'data': []
                }

            coll.set_fields(None) # for search we need all fields, except for exclude_fields
            for fld in metadata['columns']:
                if 'processable' in fld:
                    check_str= fld['type'] == 'string'
                    check_excl= fld['key'] not in exclude_fields
                    if fld['processable'] and check_str and check_excl:
                        search_query= { fld['key']: regx }
                        coll.set_query(search_query)
                        found= coll.get_data(dbconn, dataset, idef, issue)
                        if len(found) > 0:
                            for found_elt in found:
                                curr_coll_dict['data'].append({
                                    'key': fld['key'],
                                    'text': found_elt[str(fld['key'])],
                                    'idef': found_elt['idef'],
                                    'parent': found_elt['parent']
                                    })
                                found_num += 1
            if len(curr_coll_dict['data']) > 0:
                ns_list.append(curr_coll_dict)

    stat_dict.update( { 'records_found': found_num } )

    return { 'stat': stat_dict, 'result': ns_list }

def search_data( request ):
    """
    search engine enter point
    """
    usrqry = request.GET.get( 'query', '' )
    scope = request.GET.get( 'scope', '' )
    strict = request.GET.get( 'strict', 'false' )
    # converting scope and strict to objects
    scope_list= scope.split(',')
    if strict == 'false':
        strict= False
    else:
        strict= True
    # cleaning user query
    usrqry= usrqry.strip()
    usrqry= re.sub('\s+', ' ', usrqry) # cleaning multiple spaces

    lookup= build_regexp(usrqry, strict)
    regx= re.compile(lookup, re.IGNORECASE)

    result= { }
    total_rec= 0

    db= rsdb.DBconnect('mongodb').dbconnect

    # 1st PASS
    tl1= time() # starting to search
    result_1= do_search(scope_list, regx, db)
    total_rec += result_1['stat']['records_found']
    tlap1= time()-tl1 # 1st pass finished
    result_1['stat'].update( { "search_time": "%0.6f" % tlap1 } )
    result['strict']= result_1

    # 2nd PASS
    second_pass_list= []
    if not strict: # second pass makes sense
        second_pass_list= usrqry.split(' ')

        result_2= { 'stat': { 'records_found': 0 }, 'result': [] } # blank dict for 2nd pass
        if len(second_pass_list) > 0:
            tl2= time() # starting to search

            for wrd in second_pass_list:
                lookup= build_regexp(wrd, True) # we look for separate words using strict
                regx= re.compile(lookup, re.IGNORECASE)
                result_2_curr= do_search(scope_list, regx, db)

                if result_2_curr['stat']['records_found'] > 0:
                    result_2['result'].append( result_2_curr['result'] )
                    result_2['stat']['records_found'] += result_2_curr['stat']['records_found']

                total_rec += result_2_curr['stat']['records_found']
                tlap2= time()-tl2 # 2nd pass finished
                result_2['stat'].update( { "search_time": "%0.6f" % tlap2 } )

            result['loose']= result_2

    tlap= time()-tl1
    result.update( {
        "search_time_total": "%0.6f" % tlap,
        'records_found_total': total_rec
        } )

    return HttpResponse( json.dumps( result ))

def string2list( in_str ):
    """ converts comma separated string to the list """
    out_list= []
    try:
        for elm in in_str.split(','):
            if '[' in elm:
                elm= elm.replace('[', '')
            if ']' in elm:
                elm= elm.replace(']', '')
            out_list.append( elm.strip().encode('utf-8') )
    except:
        pass

    return out_list

def build_idef_regexp( curr_idef ):
    """ build regexp quering collection """
    level_num= curr_idef.count('-')
    if level_num > 0: # deeper than 'a'
        idef_srch= curr_idef.rsplit('-', 1)[0]
        lookup_idef= "^%s\-\d+$" % idef_srch
        curr_idef= idef_srch
        level= 1
        while level < level_num:
            idef_srch= curr_idef.rsplit('-', 1)[0]
            lookup_idef += "|^%s\-\d+$" % idef_srch
            curr_idef= idef_srch
            level += 1
        lookup_idef += "|^([A-Z]|\d)+$"
    else: # just query the highest level
        lookup_idef= "^([A-Z]|\d)+$"

    return lookup_idef

def build_query( idef_list ):
    lookup, i= "", 0
    for idef in idef_list:
        i += 1
        lookup_idef= build_idef_regexp( idef )

        lookup += "(%s)|" % lookup_idef
        if i == len(idef_list):
            lookup= lookup[:-1] # cutting the last symbol | in case it's the end of list

    if len(idef_list) == 1: # single idef
        lookup= lookup[1:-1] # cutting ( and )

    return lookup

# get initial_data + subtrees to searched nodes
def get_searched_data( request ):
    response_dict = {
        'dataset': int( request.GET.get( 'dataset', -1 ) ),
        'view': int( request.GET.get( 'view', -1 ) ),
        'issue': request.GET.get( 'issue', '' ).encode('utf-8'),
        'idef': string2list( request.GET.get( 'idef', '' ) ),
        'regexp': True
    }

    find_query= build_query( response_dict['idef'] )
    # regexpquery= re.compile(find_query, re.IGNORECASE)

    db= rsdb.DBconnect("mongodb").dbconnect
    coll= rsdb.Collection(query= { 'idef': { '$regex': find_query} })

    return_data = {}
    return_data['rows']= coll.get_data(
        db, response_dict['dataset'], response_dict['view'], response_dict['issue']
        )
    return_data['perspective']= coll.metadata_complete

    if 'query' in return_data['perspective']: # not json serializable
        try:
            sr= json.dumps( return_data['perspective']['query'] )
        except: # not json serializable!
            if 'idef' in return_data['perspective']['query']:
                return_data['perspective']['query']['idef']= find_query # re-write it with plain regexp
        del return_data['perspective']['query']

    return HttpResponse( json.dumps(return_data) )

# store front-end state as a permalink in mongo
@csrf_exempt
def store_state( request ):
    data = request.GET.get( 'state', '' )
    #
    # store in mongo, create uniq idef and send it back to front-end
    #

    return HttpResponse( json.dumps({'id': '1000'}) ) #replace '1000' with uniq idef

# init application prepared to handle restore data
def init_restore( request, idef ):
    template = loader.get_template( "restore.html" )
    context = Context({
        'meta': get_ms_nav(),
        'idef': idef
    })
    return HttpResponse( template.render( context ))

#restore front-end state from mongo
def restore_state( request ):
    idef = request.GET.get( 'idef', '-1' )
    data = 'get_me_from_mongo_my_name_is_' + idef

    return HttpResponse( data )

# list of possible ajax calls
func_dict = {
    # get a list of perspectives after choosing a certain collection
    "choose_collection": choose_collection,

    # get data from DB when the first time a perspective is chosen
    "get_init_data": get_init_data,

    # get a sub-level data from DB
    "get_node": get_node,

    # to be implemented
    }

def get_page( data ):
    template = loader.get_template( "test.html" )
#     context = Context( tmp_solution_for_metadata() )
    context = Context( get_ms_nav() )
    return HttpResponse( template.render( context ))

def app_page( request ):
    data = request.GET
    if data == {}:
        return get_page( request )
    else:
        function_id = data['action']
        return func_dict[function_id]( data )

def redirect( request ):
    return HttpResponseRedirect('/app')

@csrf_exempt
def feedback_email( request ):
    from_email = request.POST.get( 'email', 'NO EMAIL PROVIDED' )
    message = request.POST.get( 'message', 'MESSAGE LEFT EMPTY' )

    send_mail( 'Raw Salad Feedback',
                message,
                from_email,
                ['ktrzewiczek@centrumcyfrowe.pl'] )

    return HttpResponse( 'Email sent' )

@csrf_exempt
def download_data( request ):
    response = HttpResponse()
    files = request.POST.get( 'csv_string' ).split( '--file--' )[:-1]

    # send one sheet as CSV and collection of sheets as ZIP
    if len( files ) == 1:
        f = files[0]
        response['Content-Type'] = 'text/csv'
        response['Content-Disposition'] = 'attachment; filename=data.csv'

        if '.csv' in f:
            response.write( open( 'site_media/csv/' + f ).read() )
        else:
            data = f.split( '|' )[:-1]

            writer = UnicodeWriter( response )
            for row in data:
                writer.writerow( row.split(';') )

    else:
        in_memory = StringIO()
        zip = ZipFile( in_memory, 'a' )

        for i, f in enumerate( files ):
            if '.csv' in f:
                csv_string = open( 'site_media/csv/' + f ).read()
            else:
                csv_string = f.replace( '|', '\n' ).encode( 'utf-8' )

            zip.writestr( 'data-'+str(i)+'.csv', csv_string )

        # fix for Linux zip files read in Windows
        for file in zip.filelist:
            file.create_system = 0

        zip.close()

        response['Content-Type'] = 'application/zip'
        response['Content-Disposition'] = "attachment; filename=collected_data.zip"

        in_memory.seek( 0 )
        response.write( in_memory.read() )

    return response

def get_ms_nav():
    db= rsdb.DBconnect("mongodb").dbconnect
    nav_full= rsdb.Navtree().get_nav_full(db)
    out= { 'meta_data': json.dumps( nav_full ) }
    return out

class UnicodeWriter:
    """
    A CSV writer which will write rows to CSV file "f",
    which is encoded in the given encoding.
    """

    def __init__(self, f, dialect=csv.excel, encoding="utf-8", **kwds):
        # Redirect output to a queue
        self.queue = cStringIO.StringIO()
        self.writer = csv.writer(self.queue, dialect=dialect, delimiter=';', **kwds)
        self.stream = f
        self.encoder = codecs.getincrementalencoder(encoding)()

    def writerow(self, row):
        self.writer.writerow([s.encode("utf-8") for s in row])
        # Fetch UTF-8 output from the queue ...
        data = self.queue.getvalue()
        data = data.decode("utf-8")
        # ... and reencode it into the target encoding
        data = self.encoder.encode(data)
        # write to the target stream
        self.stream.write(data)
        # empty queue
        self.queue.truncate(0)

    def writerows(self, rows):
        for row in rows:
            self.writerow(row)
<|endoftext|>


<commit_before>import sys, os, time, logging
from telemetry import gps
from telemetry import temperature
from telemetry import sound
from telemetry import gas
from telemetry import button
from telemetry import flightrecorder
from telemetry import flightrecord
from telemetry import lcd

dbPath = os.environ.get('DB_PATH') or '/opt/telemetry-data/data.db'
logPath = os.environ.get('LOG_PATH') or '/opt/telemetry-data/event.log'
gpsPath = os.environ.get('GPS_PATH') or '/dev/ttyS0'
gpsBaud = os.environ.get('GPS_BAUD') or 4800
satPath = os.environ.get('SAT_PATH')
satBaud = os.environ.get('SAT_BAUD')
pidFilePath = os.environ.get('PID_PATH') or '/var/run/datalogging.pid'
tempSensorPin = 0
soundSensorPin = 1
gasSensorPin = 2
soundSensorPin = ''
pushButtonPin = 3

class Main():
    dataLoggingEnabled = False
    runButtonPressed = False
    def getLCD(self):
        self.logMessage("Loading: LCD Screen...")
        return lcd.LCD()
    def getDatabase(self):
        self.logMessage("Loading: SQLite Database...")
        return flightrecorder.Database(dbPath)
    def getSatModem(self):
        self.logMessage("Loading: Satellite Modem...")
    def getGPS(self):
        self.logMessage("Loading: GPS Module...")
        return gps.GPS(gpsPath, gpsBaud, self.logger)
    def getSensors(self):
        self.logMessage("Loading: GrovePi Sensor Configuration...")
        sensors = []
        self.logMessage("Loading: LM35 Temperature Sensor...")
        tempSensor = temperature.Temperature(tempSensorPin, self.logger)
        sensors.append(tempSensor)
        #self.logMessage("Loading: Sound Sensor...")
        #soundSensor = sound.Sound(soundSensorPin, self.logger)
        #sensors.append(soundSensor)
        #self.logMessage("Loading: Gas Sensor...")
        #gasSensor = gas.Gas(gasSensorPin, self.logger)
        #sensors.append(gasSensor)
        return sensors
    def getButton(self):
        return button.Button(pushButtonPin, self.logger)
    def loadModules(self):
        self.database = self.getDatabase()
        self.satModem = self.getSatModem()
        self.gps = self.getGPS()
        self.sensorList = self.getSensors()
        self.dataLoggingButton = self.getButton()
        self.lcd = self.getLCD()
        self.getDataLoggingStatus()
    def getDataLoggingStatus(self):
        dataLogging = self.findDataLoggingPidFile()
        pidFilePresent = self.isPidFilePresent()
    def isPidFilePresent(self):
        return os.path.isfile(pidFilePath)
    def savePidFile():
        pid = str(os.getpid())
        file(pidFilePath,'w+').write("%s\n" % pid)
    def setDataLoggingStatus(self, dataLoggingStatus):
        self.dataLoggingEnabled = dataLoggingStatus
        if dataLoggingStatus:
            self.savePidFile()
    def getCurrentTime(self):
        return time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime())
    def logMessage(self, message):
        if(self.logger and message):
            logging.info(message)
    def setupLogging(self):
        logging.basicConfig(filename=logPath, format='%(asctime)s gomake:: %(message)s', level=logging.INFO)
        self.logger = logging.getLogger()
    def isDataLoggingEnabled(self):
        if(not self.dataLoggingEnabled):
            isButtonPressed = self.dataLoggingButton.read() == '1'
            if(isButtonPressed):
                self.setDataLoggingStatus(True)
                self.setLCDStatus()
        return self.dataLoggingEnabled
    def readSensorValues(self):
        sensorValues = {}
        for sensor in self.sensorList:
            sensorType = sensor.getType()
            sensorValue = sensor.read()
            sensorValues[sensorType] = sensorValue
            time.sleep(0.5)
        return sensorValues
    def setLCDStatus(self):
	runStatus = 'Y' if self.runButtonPressed else 'N'
        recStatus = 'Y' if self.dataLoggingEnabled else 'N'
        statusString = 'RUN: ' + runStatus + ' REC: ' + recStatus
        if(self.lcd):
            self.lcd.setStatus(statusString)
            self.lcd.flashColor()
    def waitForButtonPressToRun(self):
		if not self.dataLoggingEnabled:
			while not self.runButtonPressed:
				if(self.dataLoggingButton.read() == '1'):
					self.runButtonPressed = True
    def run(self):
        self.logMessage('Beginning run loop...')
	self.setLCDStatus()
        while True:
            try:
                timestamp = self.getCurrentTime()
                coordinates = self.gps.read()
                #Read Sensor values
                sensorValues = self.readSensorValues()
                record = flightrecord.FlightRecord(timestamp, coordinates, sensorValues)
                #Log in log
                self.logMessage(record.getLogFormat())
                if(self.isDataLoggingEnabled()):
                    self.logMessage('Writing to database...')
                    #Record in Database
                    self.database.saveFlightRecord(record.getDatabaseFormat())
                    #Send Satellite Message
            except Exception as e:
                logging.exception(e)
    def __init__(self):
        self.setupLogging()
        self.loadModules()

if __name__ == '__main__':
    telemetry = Main()
    telemetry.waitForButtonPressToRun()
    telemetry.run()

<commit_msg>finally fixes config on boot issue<commit_after>import sys, os, time, logging
from telemetry import gps
from telemetry import temperature
from telemetry import sound
from telemetry import gas
from telemetry import button
from telemetry import flightrecorder
from telemetry import flightrecord
from telemetry import lcd

dbPath = os.environ.get('DB_PATH') or '/opt/telemetry-data/data.db'
logPath = os.environ.get('LOG_PATH') or '/opt/telemetry-data/event.log'
gpsPath = os.environ.get('GPS_PATH') or '/dev/ttyS0'
gpsBaud = os.environ.get('GPS_BAUD') or 4800
satPath = os.environ.get('SAT_PATH')
satBaud = os.environ.get('SAT_BAUD')
pidFilePath = os.environ.get('PID_PATH') or '/opt/telemetry-data/datalogging.pid'
tempSensorPin = 0
soundSensorPin = 1
gasSensorPin = 2
soundSensorPin = ''
pushButtonPin = 3

class Main():
    dataLoggingEnabled = False
    runButtonPressed = False
    def getLCD(self):
        self.logMessage("Loading: LCD Screen...")
        return lcd.LCD()
    def getDatabase(self):
        self.logMessage("Loading: SQLite Database...")
        return flightrecorder.Database(dbPath)
    def getSatModem(self):
        self.logMessage("Loading: Satellite Modem...")
    def getGPS(self):
        self.logMessage("Loading: GPS Module...")
        return gps.GPS(gpsPath, gpsBaud, self.logger)
    def getSensors(self):
        self.logMessage("Loading: GrovePi Sensor Configuration...")
        sensors = []
        self.logMessage("Loading: LM35 Temperature Sensor...")
        tempSensor = temperature.Temperature(tempSensorPin, self.logger)
        sensors.append(tempSensor)
        #self.logMessage("Loading: Sound Sensor...")
        #soundSensor = sound.Sound(soundSensorPin, self.logger)
        #sensors.append(soundSensor)
        #self.logMessage("Loading: Gas Sensor...")
        #gasSensor = gas.Gas(gasSensorPin, self.logger)
        #sensors.append(gasSensor)
        return sensors
    def getButton(self):
        return button.Button(pushButtonPin, self.logger)
    def loadModules(self):
        self.database = self.getDatabase()
        self.satModem = self.getSatModem()
        self.gps = self.getGPS()
        self.sensorList = self.getSensors()
        self.dataLoggingButton = self.getButton()
        self.lcd = self.getLCD()
        self.getDataLoggingStatus()
    def getDataLoggingStatus(self):
	self.dataLoggingEnabled = self.isPidFilePresent()
        return self.dataLoggingEnabled
    def isPidFilePresent(self):
        return os.path.isfile(pidFilePath)
    def savePidFile(self):
        pid = str(os.getpid())
        file(pidFilePath,'w+').write("%s\n" % pid)
    def setDataLoggingStatus(self, dataLoggingStatus):
        self.dataLoggingEnabled = dataLoggingStatus
        if dataLoggingStatus:
            self.savePidFile()
    def getCurrentTime(self):
        return time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime())
    def logMessage(self, message):
        if(self.logger and message):
            logging.info(message)
    def setupLogging(self):
        logging.basicConfig(filename=logPath, format='%(asctime)s gomake:: %(message)s', level=logging.INFO)
        self.logger = logging.getLogger()
    def isDataLoggingEnabled(self):
        if(not self.dataLoggingEnabled):
            isButtonPressed = self.dataLoggingButton.read() == '1'
            if(isButtonPressed):
                self.setDataLoggingStatus(True)
                self.setLCDStatus()
        return self.dataLoggingEnabled
    def readSensorValues(self):
        sensorValues = {}
        for sensor in self.sensorList:
            sensorType = sensor.getType()
            sensorValue = sensor.read()
            sensorValues[sensorType] = sensorValue
            time.sleep(0.5)
        return sensorValues
    def setLCDStatus(self):
	runStatus = 'Y' if self.runButtonPressed else 'N'
        recStatus = 'Y' if self.dataLoggingEnabled else 'N'
        statusString = 'RUN: ' + runStatus + ' REC: ' + recStatus
        if(self.lcd):
            self.lcd.setStatus(statusString)
            self.lcd.flashColor()
    def waitForButtonPressToRun(self):
		if not self.dataLoggingEnabled:
			while not self.runButtonPressed:
				if(self.dataLoggingButton.read() == '1'):
					self.runButtonPressed = True
		else:
			self.runButtonPressed = True
    def run(self):
        self.logMessage('Beginning run loop...')
	self.setLCDStatus()
        while True:
            try:
                timestamp = self.getCurrentTime()
                coordinates = self.gps.read()
                #Read Sensor values
                sensorValues = self.readSensorValues()
                record = flightrecord.FlightRecord(timestamp, coordinates, sensorValues)
                #Log in log
                self.logMessage(record.getLogFormat())
                if(self.isDataLoggingEnabled()):
                    self.logMessage('Writing to database...')
                    #Record in Database
                    self.database.saveFlightRecord(record.getDatabaseFormat())
                    #Send Satellite Message
            except Exception as e:
                logging.exception(e)
    def __init__(self):
        self.setupLogging()
        self.loadModules()

if __name__ == '__main__':
    telemetry = Main()
    telemetry.waitForButtonPressToRun()
    telemetry.run()

<|endoftext|>