def _makeEpilogue(self):
     """
 Adds code that only runs at the end
 :return str: statements
 """
     sa = StatementAccumulator()
     sa.add("")
     sa.add("%s.controller.startBlock('Epilogue')" % API_OBJECT)
     sa.add(self._table.getEpilogue().getFormula())
     sa.add("%s.controller.endBlock()" % API_OBJECT)
     return sa.get()
 def _makeVariablePrintStatements(self):
     """
 Creates the print statements for all variables in the table.
 For each variable A:
   print ('A = %s' % str(A))
 :return str statements:
 """
     sa = StatementAccumulator()
     for column in self._table.getColumns():
         statement = """print ('%%s =  %%s' %% ("%s", str(%s))) """ % (column.getName(), column.getName())
         sa.add(statement)
     return sa.get()
    def _makeClosingException(self, is_absolute_linenumber=True):
        """
    Raises exceptions that have been recorded.
    :param bool is_absolute_linenumber:
    """
        sa = StatementAccumulator()
        statement = """
if %s.controller.getException() is not None:
  raise Exception(%s.controller.formatError(is_absolute_linenumber=%s))""" % (
            API_OBJECT,
            API_OBJECT,
            is_absolute_linenumber,
        )
        sa.add(statement)
        return sa.get()
 def _makeClosingOfFormulaEvaluationLoop(self, **kwargs):
     """
 Creates the statements at the end of the formula evaluation
 loop.
   1. Statements that update objects
   2. Assignments of variables to columns
   3. Loop termination checks
 """
     sa = StatementAccumulator()
     sa.add("")
     sa.add("%s.controller.endAnIteration()" % API_OBJECT)
     sa.add("")
     return sa.get()
 def _makeFormulaImportStatements(self, directory, import_path=""):
     """
 Construct import statements for the imports implied by the
 functions used in a formula. The approach taken isn't
 very robust:
   1. Find all .py files in the user's python directory. The
      function name should be the same as the file name.
   2. If a formula contains the file name (function name), then
      an import is generated.
 :param str directory: directory to search
 :param str import_path: path for the import
 :return str: import statements for files in the user directory
 """
     formulas = [c.getFormula() for c in self._table.getColumns() if not (c.getFormula() is None)]
     formulas.append(self._table.getPrologue().getFormula())
     formulas.append(self._table.getEpilogue().getFormula())
     python_filenames = self._findFilenames(directory)
     # Determine which files are referenced in a formula
     referenced_filenames = []
     for name in python_filenames:
         for formula in formulas:
             if name in formula:
                 referenced_filenames.append(name)
                 break
     # Construct the import statements
     sa = StatementAccumulator()
     for name in referenced_filenames:
         if len(import_path) == 0:
             sa.add("from %s import %s" % (name, name))
         else:
             sa.add("from %s.%s import %s" % (import_path, name, name))
     return sa.get()
 def _makeColumnValuesAssignmentStatements(self, **kwargs):
     """
 Creates statements that assign column values to variables.
 Note that the assumption is that the variable name is the same
 as the column name
 """
     sa = StatementAccumulator()
     sa.add("\n")
     sa.add("# Assign program variables to columns values.")
     columns = self._getSelectedColumns(**kwargs)
     for column in columns:
         name = column.getName(is_global_name=False)
         statement = "%s.setColumnValue('%s', %s)" % (API_OBJECT, name, name)
         sa.add(statement)
     return sa.get()
 def _makeVariableAssignmentStatements(self, prefix="", **kwargs):
     """
 Creates statements that assign column values to variables.
 :param str prefix: prefix to construct full API object
 :return str: assignment statements
 """
     sa = StatementAccumulator()
     sa.add("# Assign column values to program variables.")
     full_object = "%s%s" % (prefix, API_OBJECT)
     columns = self._getSelectedColumns(**kwargs)
     for column in columns:
         name = column.getName(is_global_name=False)
         statement = "%s = %s.getColumnValue('%s')" % (name, full_object, name)
         sa.add(statement)
     return sa.get()
    def _makeAPIPluginInitializationStatements(self, function_name, prefix=""):
        """
    :param str function_name:
    :param str prefix: prefix for API Object
    """
        sa = StatementAccumulator()
        sa.add("from scisheets.core import api as api")
        full_object = "%s%s" % (prefix, API_OBJECT)
        filepath = api_util.getTableCopyFilepath(function_name, self._user_directory)
        statement = """%s = api.APIPlugin('%s')
%s.initialize()
_table = %s.getTable()
""" % (
            full_object,
            filepath,
            full_object,
            full_object,
        )
        sa.add(statement)
        return sa.get()
    def _makeAPIInitializationStatements(self, create_API_object=False):
        """
    :param bool create_API_object: True means that code will be generated
                                 that creates the API object.
    """
        sa = StatementAccumulator()
        sa.add("from scisheets.core import api as api")
        statement = """
_table = api.readTableFromFile('%s')
_table.setNamespace(globals())
%s = api.APIFormulas(_table) 
""" % (
            self._table.getFilepath(),
            API_OBJECT,
        )
        if not create_API_object:
            new_statement = statement.replace("\n", "\n#")
            header = "# Uncomment the following to execute standalone"
            statement = "%s\n#%s" % (header, new_statement)
        sa.add(statement)
        return sa.get()
Esempio n. 10
0
  def _wrapProgram(self):
    """
    Puts a wrapper around the program so that an exception can
    be caught and its location determined within the program.
    :returns str: program wrapped in try/catch blocks
    :sideeffects: puts CONTROLLER object in the namespace
    """
    self._namespace[CONTROLLER] =  self._controller
    sa = StatementAccumulator()
    sa.add("try:")
    sa.indent(1)
    statement = "%s.startBlock('%s')" % (CONTROLLER, self._program_name)
    sa.add(statement)
    sa.add(self._program)
    statement = "%s.endBlock()" % CONTROLLER
    sa.add(statement)
    sa.indent(-1)
    statement = """
except Exception as exc:
  %s.exceptionForBlock(exc)""" % CONTROLLER
    sa.add(statement)
    return sa.get()
Esempio n. 11
0
    def _makeFormulaEvaluationStatements(self, **kwargs):
        """
    Constructs a script to evaluate table formulas.
    :return str: statements
    Notes: (1) Iterate N (#formulas) times to handle dependencies
               between formulas
    """
        # Initializations
        sa = StatementAccumulator()
        formula_columns = self._formulaColumns()
        num_formulas = len(formula_columns)
        if num_formulas == 0:
            return []
        # Statements that evaluate the formulas
        # Iteratively evaluate the formulas. The iteration
        # terminates under three conditions:
        #  1. No exception and no change in table data since the
        #     last iteration.
        #  2. No exception and the iteration count is equal to the
        #     number of columns.
        #  3. The iteration count exceeds a maximum value.
        statement = """
# Formula evaluation loop
%s.controller.initializeLoop()
while not %s.controller.isTerminateLoop():
""" % (
            API_OBJECT,
            API_OBJECT,
        )
        sa.add(statement)
        sa.indent(1)
        sa.add("%s.controller.startAnIteration()" % API_OBJECT)
        # Formula Evaluation block header
        sa.add("# Formula Execution Blocks")
        # Formula Evaluation block formulas
        for column in formula_columns:
            sa.add("try:")
            sa.indent(1)
            colnm = column.getName(is_global_name=False)
            sa.add("# Column %s" % colnm)
            statement = "%s.controller.startBlock('%s')" % (API_OBJECT, colnm)
            sa.add(statement)
            statement = column.getFormulaStatement()
            sa.add(statement)
            sa.add("%s.controller.endBlock()" % API_OBJECT)
            if column.isExpression():
                sa.add("%s = %s.coerceValues('%s', %s)" % (colnm, API_OBJECT, colnm, colnm))
            sa.indent(-1)
            sa.add("except Exception as exc:")
            sa.indent(1)
            sa.add("%s.controller.exceptionForBlock(exc)" % API_OBJECT)
            sa.indent(-1)
            sa.add(" ")
        # Formula Evaluation block footer
        # End of loop
        statement = self._makeClosingOfFormulaEvaluationLoop(**kwargs)
        sa.add(statement)
        return sa.get()
Esempio n. 12
0
 def _makePrologue(self, **kwargs):
     """
 Creates the imports that go at the head of the file
 :return str: statements
 """
     sa = StatementAccumulator()
     # Import the plugins
     if self._user_directory is not None:
         statement = self._makeFormulaImportStatements(self._user_directory)
         sa.add(statement)
     statement = self._makeFormulaImportStatements(self._plugin_directory, import_path=self._plugin_path)
     sa.add(statement)
     # Add the table prologue
     sa.add("%s.controller.startBlock('Prologue')" % API_OBJECT)
     sa.add(self._table.getPrologue().getFormula())
     sa.add("%s.controller.endBlock()" % API_OBJECT)
     return sa.get()
Esempio n. 13
0
    def makeTestProgram(self, function_name=None, inputs=None, outputs=None):
        """
    Creates a program that tests the function exported for the table
    :param function_name: string name of the function to be created
    :param inputs: list of column names that are input to the function
    :param outputs: list of columns that are output from the function
    :return (str error, str program):
    """
        sa = StatementAccumulator()
        prefix = "self."
        output_str = _makeOutputStr(outputs)
        statement = '''"""
Tests for %s
"""

from scisheets.core import api as api
from %s import %s
import unittest


#############################
# Tests
#############################
# pylint: disable=W0212,C0111,R0904
class Test%s(unittest.TestCase):
''' % (
            function_name,
            function_name,
            function_name,
            function_name,
        )
        sa.add(statement)
        # Construct setup method
        sa.indent(1)
        sa.add("def setUp(self):")
        sa.indent(1)
        statement = self._makeAPIPluginInitializationStatements(function_name, prefix=prefix)
        sa.add(statement)
        sa.indent(-1)
        # Construct the test function header
        sa.add("def testBasics(self):")
        sa.indent(1)
        # Assign values to the columns
        sa.add(self._makeVariableAssignmentStatements(prefix=prefix, only_includes=inputs))
        # Construct the call to the function being tested
        statement = _makeOutputStr(outputs)
        statement += " = %s(" % function_name
        statement += ",".join(inputs)
        statement += ")"
        sa.add(statement)
        # Construct the tests
        for column_name in outputs:
            statement = "self.assertTrue(self.%s.compareToColumnValues('%s', %s))" % (
                API_OBJECT,
                column_name,
                column_name,
            )
            sa.add(statement)
        sa.indent(-2)
        # Construct the program epilogue
        statement = """

if __name__ == '__main__':
  unittest.main()"""
        sa.add(statement)
        return sa.get()
Esempio n. 14
0
    def makeFunctionProgram(self, function_name, inputs, outputs):
        """
    Creates a function for the table
    :param function_name: string name of the function to be created
    :param inputs: list of column names that are input to the function
    :param outputs: list of columns that are output from the function
    :return str program: Program as a string
    """
        # Initializations
        sa = StatementAccumulator()
        # Program Prologue
        # TODO: This won't work with nested columns
        statement = """# Export of the table %s

    """ % self._table.getName(
            is_global_name=False
        )
        sa.add(statement)
        sa.add("")
        # Make the function definition. This must enclose the prologue
        # and epilogue
        sa.add(_makeFunctionStatement(function_name, inputs))
        sa.indent(1)
        sa.add(self._makeAPIPluginInitializationStatements(function_name))
        excludes = list(inputs)
        excludes.extend(outputs)
        sa.add(self._makePrologue(excludes=excludes))
        # Assign the column values to function variables.
        # Note that inputs and outputs are not assigned.
        #
        sa.add(self._makeFormulaEvaluationStatements(excludes=excludes))
        sa.add(self._makeClosingException())
        sa.add(self._makeEpilogue())
        sa.add(_makeReturnStatement(outputs))
        return sa.get()
Esempio n. 15
0
    def makeExportScriptProgram(self):
        """
	    Creates an exported python script.
    :return str program: Program as a string
    """
        sa = StatementAccumulator()
        # TODO: This won't work with nested columns
        statement = """# Script that runs formulas in the table %s.

    """ % self._table.getName(
            is_global_name=False
        )
        sa.add(statement)
        sa.add(self._makeAPIInitializationStatements(create_API_object=True))
        sa.add(self._makePrologue())
        sa.add(self._makeFormulaEvaluationStatements())
        sa.add(self._makeClosingException())
        sa.add(self._makeEpilogue())
        sa.add(self._makeVariablePrintStatements())
        return sa.get()
class TestStatementAccumulator(unittest.TestCase):

  def setUp(self):
    self.sa = StatementAccumulator()

  def testAdd(self):
    statement = "This is a test."
    self.sa.add(statement)
    self.assertEqual(self.sa._statements[0], statement)
    statement = "This is another test."
    self.sa.add(statement)
    self.assertEqual(self.sa._statements[1], statement)

  def testAddWithIndent(self):
    statement = "This is a test."
    self.sa.add(statement)
    self.sa.indent(1)
    statement = "This is another test."
    self.sa.add(statement)
    self.assertEqual(self.sa._statements[1], "  %s" % statement)
    self.sa.indent(1)
    statement = "This is another test."
    self.sa.add(statement)
    self.assertEqual(self.sa._statements[2], "    %s" % statement)
    self.sa.indent(-1)
    statement = "This is another test."
    self.sa.add(statement)
    self.assertEqual(self.sa._statements[3], "  %s" % statement)

  def testGet(self):
    first_statement = "This is a test."
    self.sa.add(first_statement)
    self.assertEqual(self.sa.get(), first_statement)
    self.sa.indent(1)
    second_statement = "This is a test."
    self.sa.add(second_statement)
    expected_result ="%s\n  %s" % (first_statement, second_statement)
    self.assertEqual(self.sa.get(), expected_result)

  def testExtra(self):
    statement = '''# Evaluation of the table %s.

    ''' % "aName"
    self.sa.add(statement)
 def setUp(self):
   self.sa = StatementAccumulator()
Esempio n. 18
0
    def makeEvaluationScriptProgram(self, create_API_object=False):
        """
    Creates a python script that evaluates the table formulas
    when there is a change to the scisheet
    :param bool create_API_object: True means that code will be generated
                                 that creates the API object.
    :return str program: Program as a string
    """
        sa = StatementAccumulator()
        # TODO: This won't work with nested columns
        statement = """# Evaluation of the table %s.

    """ % self._table.getName(
            is_global_name=False
        )
        sa.add(statement)
        sa.add(self._makeAPIInitializationStatements(create_API_object=create_API_object))
        sa.add("try:")
        sa.indent(1)
        sa.add(self._makePrologue())
        sa.add(self._makeFormulaEvaluationStatements())
        statement = "if %s.controller.getException() is None:" % API_OBJECT
        sa.add(statement)
        sa.indent(1)
        sa.add(self._makeEpilogue())
        sa.indent(-2)
        # Handle exceptions in the Prologue and Epilogue
        statement = (
            """
except Exception as exc:
  %s.controller.exceptionForBlock(exc)"""
            % API_OBJECT
        )
        sa.add(statement)
        sa.add(self._makeClosingException(is_absolute_linenumber=False))
        return sa.get()