def test_creation(self):
        user = User(username='******')
        sheet = Sheet(owner=user)
        self.assertEquals(sheet.owner, user)
        self.assertEquals(sheet.name, 'Untitled')
        self.assertEquals(sheet.width, 52)
        self.assertEquals(sheet.height, 1000)
        self.assertEquals(sheet.timeout_seconds, 55)
        self.assertEquals(sheet.allow_json_api_access, False)
        self.assertEquals(sheet.is_public, False)
        self.assertEquals(sheet.contents_json, worksheet_to_json(Worksheet()))
        self.assertEquals(sheet.column_widths, {})
        self.assertEquals(
            sheet.usercode,
            dedent("""
                load_constants(worksheet)

                # Put code here if it needs to access constants in the spreadsheet
                # and to be accessed by the formulae.  Examples: imports,
                # user-defined functions and classes you want to use in cells.

                evaluate_formulae(worksheet)

                # Put code here if it needs to access the results of the formulae.
            """)
        )
        self.assertEquals(len(sheet.api_key), 36)
        self.assertIsNotNone(re.match('[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}', sheet.api_key))
    def test_creation(self):
        user = User(username='******')
        sheet = Sheet(owner=user)
        self.assertEquals(sheet.owner, user)
        self.assertEquals(sheet.name, 'Untitled')
        self.assertEquals(sheet.width, 52)
        self.assertEquals(sheet.height, 1000)
        self.assertEquals(sheet.timeout_seconds, 55)
        self.assertEquals(sheet.allow_json_api_access, False)
        self.assertEquals(sheet.is_public, False)
        self.assertEquals(sheet.contents_json, worksheet_to_json(Worksheet()))
        self.assertEquals(sheet.column_widths, {})
        self.assertEquals(
            sheet.usercode,
            dedent("""
                load_constants(worksheet)

                # Put code here if it needs to access constants in the spreadsheet
                # and to be accessed by the formulae.  Examples: imports,
                # user-defined functions and classes you want to use in cells.

                evaluate_formulae(worksheet)

                # Put code here if it needs to access the results of the formulae.
            """))
        self.assertEquals(len(sheet.api_key), 36)
        self.assertIsNotNone(
            re.match(
                '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}',
                sheet.api_key))
Example #3
0
    def test_empty_worksheet_to_json(self):
        worksheet = Worksheet()

        worksheet_json = worksheet_to_json(worksheet)
        self.assertEquals(json.loads(worksheet_json), {
            "_console_text": "",
            "_usercode_error": None,
        })
    def test_empty_worksheet_to_json(self):
        worksheet = Worksheet()

        worksheet_json = worksheet_to_json(worksheet)
        self.assertEquals(
            json.loads(worksheet_json),
            {
                "_console_text": "",
                "_usercode_error": None,
            }
        )
Example #5
0
    def test_nan_values_are_ignored(self):
        self.maxDiff = None

        worksheet = Worksheet()
        worksheet.A1.value = float('nan')
        worksheet.A2.value = float('inf')
        worksheet.A3.value = float('-inf')

        worksheet_json = worksheet_to_json(worksheet)
        roundtripped = jsonlib.read(worksheet_json)
        self.assertEquals(roundtripped["1,1"]['formatted_value'], 'nan')
        self.assertEquals(roundtripped["1,2"]['formatted_value'], 'inf')
        self.assertEquals(roundtripped["1,3"]['formatted_value'], '-inf')
        self.assertFalse('value' in roundtripped["1,1"])
        self.assertFalse('value' in roundtripped["1,2"])
        self.assertFalse('value' in roundtripped["1,3"])
    def test_nan_values_are_ignored(self):
        self.maxDiff = None

        worksheet = Worksheet()
        worksheet.A1.value = float('nan')
        worksheet.A2.value = float('inf')
        worksheet.A3.value = float('-inf')

        worksheet_json = worksheet_to_json(worksheet)
        roundtripped = jsonlib.read(worksheet_json)
        self.assertEquals(roundtripped["1,1"]['formatted_value'], 'nan')
        self.assertEquals(roundtripped["1,2"]['formatted_value'], 'inf')
        self.assertEquals(roundtripped["1,3"]['formatted_value'], '-inf')
        self.assertFalse('value' in roundtripped["1,1"])
        self.assertFalse('value' in roundtripped["1,2"])
        self.assertFalse('value' in roundtripped["1,3"])
Example #7
0
    def test_dependencies_get_put_in_json_as_array_of_arrays(self):
        self.maxDiff = None

        worksheet = Worksheet()
        worksheet.A1.dependencies = [(1, 2)]
        worksheet._console_text = ""

        worksheet_json = worksheet_to_json(worksheet)

        self.assertEquals(
            json.loads(worksheet_json), {
                u"1,1": {
                    u"formula": None,
                    u"formatted_value": u"",
                    u"dependencies": [[1, 2]],
                },
                u"_console_text": u"",
                u"_usercode_error": None,
            })
Example #8
0
    def test_run_worksheet_should_return_worksheet_with_calculated_values_only(
            self, mock_urllib2):
        self.maxDiff = None

        original_sheet = Worksheet()

        original_sheet.A2.formula = '1'
        original_sheet.A2.value = 1

        original_sheet.C3.formula = '5'
        original_sheet.C3.value = 5

        original_sheet.E4.formula = '=A2 + C3'
        original_sheet.E4.value = 6

        expected_sheet = Worksheet()
        expected_sheet.name = 'Untitled'
        for (col, row), cell in original_sheet.items():
            expected_sheet[col, row].value = cell.value
        foreign_sheet = Sheet()
        foreign_sheet.owner = User(username='******', password='******')
        foreign_sheet.owner.save()
        foreign_sheet.contents_json = worksheet_to_json(original_sheet)
        foreign_sheet.calculate()

        mock_opener = mock_urllib2.build_opener.return_value
        mock_urlopen_file = mock_opener.open.return_value
        mock_urlopen_file.read.return_value = _sheet_to_value_only_json(
            foreign_sheet.name,
            worksheet_from_json(foreign_sheet.contents_json))

        worksheet_url = 'ws_url/'
        result = run_worksheet(worksheet_url, None, sentinel.private_key)

        target_url = '%sv%s/json/' % (worksheet_url, CURRENT_API_VERSION)
        self.assertCalledOnce(mock_opener.open,
                              target_url,
                              data=urlencode({
                                  'dirigible_l337_private_key':
                                  sentinel.private_key
                              }))
        self.assertEquals(type(result), Worksheet)
        self.assertEquals(result, expected_sheet)
    def test_dependencies_get_put_in_json_as_array_of_arrays(self):
        self.maxDiff = None

        worksheet = Worksheet()
        worksheet.A1.dependencies = [(1, 2)]
        worksheet._console_text = ""

        worksheet_json = worksheet_to_json(worksheet)

        self.assertEquals(
            json.loads(worksheet_json),
            {
                u"1,1" : {
                    u"formula" : None,
                    u"formatted_value" : u"",
                    u"dependencies" : [[1, 2]],
                },

                u"_console_text": u"",
                u"_usercode_error": None,
            }
        )
    def test_run_worksheet_should_return_worksheet_with_calculated_values_only(self, mock_urllib2):
        self.maxDiff = None

        original_sheet = Worksheet()

        original_sheet.A2.formula = '1'
        original_sheet.A2.value = 1

        original_sheet.C3.formula = '5'
        original_sheet.C3.value = 5

        original_sheet.E4.formula = '=A2 + C3'
        original_sheet.E4.value = 6

        expected_sheet = Worksheet()
        expected_sheet.name = 'Untitled'
        for (col, row), cell in original_sheet.items():
            expected_sheet[col, row].value = cell.value
        foreign_sheet = Sheet()
        foreign_sheet.owner = User(username='******', password='******')
        foreign_sheet.owner.save()
        foreign_sheet.contents_json = worksheet_to_json(original_sheet)
        foreign_sheet.calculate()

        mock_opener = mock_urllib2.build_opener.return_value
        mock_urlopen_file = mock_opener.open.return_value
        mock_urlopen_file.read.return_value = _sheet_to_value_only_json(
            foreign_sheet.name, worksheet_from_json(foreign_sheet.contents_json)
        )

        worksheet_url = 'ws_url/'
        result = run_worksheet(worksheet_url, None, sentinel.private_key)

        target_url = '%sv%s/json/' % (worksheet_url, CURRENT_API_VERSION)
        self.assertCalledOnce(mock_opener.open, target_url, data=urlencode({'dirigible_l337_private_key': sentinel.private_key}))
        self.assertEquals(type(result), Worksheet)
        self.assertEquals(result, expected_sheet)
Example #11
0
    def test_worksheet_with_data_to_json(self):
        self.maxDiff = None

        worksheet = Worksheet()

        worksheet.B29.formula = "a constant"
        worksheet.B29.value = 56
        worksheet.B29.formatted_value = "fifty-six"
        worksheet.B29.error = "b0rken"

        worksheet.C29.formula = "another constant"
        worksheet.C29.value = ["value", "is", "a", "list"]
        worksheet.C29.formatted_value = "[the same list]"

        class UnJSONableObject(object):
            def __str__(self):
                return "The result of str-ing the object"

        worksheet.D29.formula = None
        worksheet.D29.value = UnJSONableObject()
        worksheet.D29.formatted_value = "The formatted object"

        worksheet.E29.formula = '=1 + 2'
        worksheet.E29.value = 3
        worksheet.E29.formatted_value = "Three"

        worksheet._console_text = "The console text"
        worksheet._usercode_error = {
            "message": "The usercode error",
            "line": 23
        }

        worksheet_json = worksheet_to_json(worksheet)

        self.assertEquals(
            json.loads(worksheet_json), {
                u"2,29": {
                    u"formula": u"a constant",
                    u"value": 56,
                    u"formatted_value": u"fifty-six",
                    u"error": u"b0rken"
                },
                u"3,29": {
                    u"formula": u"another constant",
                    u"value": [u"value", u"is", u"a", u"list"],
                    u"formatted_value": u"[the same list]"
                },
                u"4,29": {
                    u"formula": None,
                    u"formatted_value": u"The formatted object",
                },
                u"5,29": {
                    u"formula": u"=1 + 2",
                    u"python_formula": u"1 + 2",
                    u"value": 3,
                    u"formatted_value": u"Three",
                },
                u"_console_text": u"The console text",
                u"_usercode_error": {
                    u"message": u"The usercode error",
                    u"line": 23
                },
            })
Example #12
0
 def test_worksheet_to_json_remembers_to_close_stringIO_stream(
         self, mock_stringio):
     worksheet = Worksheet()
     mock_stringio.return_value = Mock()
     worksheet_to_json(worksheet)
     self.assertCalledOnce(mock_stringio.return_value.close)
Example #13
0
 def jsonify_worksheet(self, worksheet):
     self.contents_json = worksheet_to_json(worksheet)
Example #14
0
class Sheet(models.Model):
    last_modified = models.DateTimeField(auto_now=True)

    version = models.IntegerField(default=0)

    owner = models.ForeignKey(User)
    name = models.TextField(default='Untitled')

    width = models.IntegerField(default=52)
    height = models.IntegerField(default=1000)

    contents_json = models.TextField(default=worksheet_to_json(Worksheet()))

    timeout_seconds = models.IntegerField(default=55)

    is_public = models.BooleanField(default=False)
    allow_json_api_access = models.BooleanField(default=False)
    api_key = models.CharField(max_length=72)

    column_widths_json = models.TextField(default='{}')

    usercode = models.TextField(
        default=dedent("""
            load_constants(worksheet)

            # Put code here if it needs to access constants in the spreadsheet
            # and to be accessed by the formulae.  Examples: imports,
            # user-defined functions and classes you want to use in cells.

            evaluate_formulae(worksheet)

            # Put code here if it needs to access the results of the formulae.
        """)
    )


    def __init__(self, *args, **kwargs):
        models.Model.__init__(self, *args, **kwargs)
        self.column_widths = jsonlib.loads(self.column_widths_json)
        if not self.api_key:
            self.api_key = str(uuid4())

    def __unicode__(self):
        return 'Sheet %d: %s' % (self.id, self.name)


    def create_private_key(self):
        self.otp = OneTimePad(user=self.owner)
        self.otp.save()
        return unicode(self.otp.guid)


    def _delete_private_key(self):
        self.otp.delete()


    def save(self, *args, **kwargs):
        if self.name == 'Untitled':
            models.Model.save(self, *args, **kwargs) # save to set self.id
            self.name = 'Sheet %d' % (self.id,)
        self.column_widths_json = jsonlib.dumps(self.column_widths)
        models.Model.save(self, *args, **kwargs)


    def unjsonify_worksheet(self):
        return worksheet_from_json(self.contents_json)


    def jsonify_worksheet(self, worksheet):
        self.contents_json = worksheet_to_json(worksheet)


    def merge_non_calc_attrs(self, sheet_in_db):
        self.name = sheet_in_db.name
        self.column_widths = sheet_in_db.column_widths


    def calculate(self):
        private_key = self.create_private_key()
        worksheet = self.unjsonify_worksheet()
        transaction.commit()
        try:
            calculate_with_timeout(worksheet, self.usercode, self.timeout_seconds, private_key)
        finally:
            self._delete_private_key()
        self.jsonify_worksheet(worksheet)
    def test_worksheet_with_data_to_json(self):
        self.maxDiff = None

        worksheet = Worksheet()

        worksheet.B29.formula = "a constant"
        worksheet.B29.value = 56
        worksheet.B29.formatted_value = "fifty-six"
        worksheet.B29.error = "b0rken"

        worksheet.C29.formula = "another constant"
        worksheet.C29.value = ["value", "is", "a", "list"]
        worksheet.C29.formatted_value = "[the same list]"

        class UnJSONableObject(object):
            def __str__(self):
                return "The result of str-ing the object"
        worksheet.D29.formula = None
        worksheet.D29.value = UnJSONableObject()
        worksheet.D29.formatted_value = "The formatted object"

        worksheet.E29.formula = '=1 + 2'
        worksheet.E29.value = 3
        worksheet.E29.formatted_value = "Three"

        worksheet._console_text = "The console text"
        worksheet._usercode_error = { "message": "The usercode error", "line": 23 }

        worksheet_json = worksheet_to_json(worksheet)

        self.assertEquals(
            json.loads(worksheet_json),
            {
                u"2,29" : {
                    u"formula" : u"a constant",
                    u"value" : 56,
                    u"formatted_value": u"fifty-six",
                    u"error": u"b0rken"
                },

                u"3,29" : {
                    u"formula" : u"another constant",
                    u"value" : [u"value", u"is", u"a", u"list"],
                    u"formatted_value": u"[the same list]"
                },

                u"4,29" : {
                    u"formula" : None,
                    u"formatted_value": u"The formatted object",
                },

                u"5,29" : {
                    u"formula" : u"=1 + 2",
                    u"python_formula" : u"1 + 2",
                    u"value": 3,
                    u"formatted_value": u"Three",
                },

                u"_console_text": u"The console text",
                u"_usercode_error": { u"message": u"The usercode error", u"line": 23 },
            }
        )
 def test_worksheet_to_json_remembers_to_close_stringIO_stream(self, mock_stringio):
     worksheet = Worksheet()
     mock_stringio.return_value = Mock()
     worksheet_to_json(worksheet)
     self.assertCalledOnce(mock_stringio.return_value.close)