Example #1
0
def test_sheets_returns_false_for_empty_values(mocker):
    patient = GSheetChecker('fake.table', 'sheet_id', 'worksheet_name',
                            'TESTING')
    patient.build_header_row_index([
        'Issue', 'Authoritative Access From', 'SGID Data Layer',
        'Refresh Cycle (Days)', 'Last Update', 'Days From Last Refresh',
        'Days to Refresh', 'Description', 'Data Source', 'Use Restrictions',
        'Website URL', 'Anchor', 'Data Type', 'PEL Layer', 'PEL Status',
        'Governance/Agreement', 'PEL Inclusion', 'Agency Contact Name',
        'Agency Contact Email', 'SGID Coordination', 'Archival Schedule',
        'Endpoint', 'Tier', 'Webapp', 'Notes', 'Deprecated'
    ])
    patient._get_data = mocker.Mock(return_value=[Cell('A1', 'fake.table')])
    mocker.patch('pygsheets.Cell.link')
    mocker.patch('pygsheets.Cell.neighbour', return_value=Cell('A2'))

    response = patient.exists()

    assert response.valid == True
    assert response.messages == {
        'Description': False,
        'Data Source': False,
        'Website URL': False,
        'Data Type': False,
        'Endpoint': False,
        'Deprecated': False,
    }
Example #2
0
def model_cell(wks: Worksheet, index: str) -> Cell:
    '''Prepare model_cell to apply to DataRange in main program'''
    cell = Cell(index)
    wks.unlink()
    cell.text_format['fontSize'] = 11
    cell.text_format['bold'] = True
    cell.borders = {'top': {'style': 'SOLID'}}
    wks.link()
    return cell
Example #3
0
    def write(self, google_doc_name, dictionary):
        worksheet = self._get_worksheet(google_doc_name)

        log_step("Clear spreadsheet...")
        self._clear_worksheet(worksheet)
        log_step("Writing cells...")
        start_time = time.time()

        cells = []
        row = 1
        languages = dictionary.languages
        languages = sorted(languages)
        for index, lang in enumerate(languages):
            column = index + 2
            cell = Cell((row, column))
            cell.value = lang
            cells.append(cell)

        row = 2
        for key in dictionary.keys():
            cell = Cell((row, 1))
            cell.value = key
            cells.append(cell)

            for index, lang in enumerate(languages):
                column = index + 2
                translated_value = dictionary.get_translation(key, lang)
                cell = Cell((row, column))
                cell.value = translated_value
                cells.append(cell)
            row += 1
        worksheet.update_cells(cell_list=cells)
        log_step("Done writing cells ({} seconds)".format(
            int(time.time() - start_time)))
Example #4
0
def test_sheets_with_duplicate_cells_returns_false(mocker):
    patient = GSheetChecker('fake.table', 'sheet_id', 'worksheet_name',
                            'TESTING')
    mocker.patch('pygsheets.Cell.link')
    patient._get_data = mocker.Mock(return_value=[
        Cell('A1', val='fake.table'),
        Cell('A2', val='fake.table')
    ])

    response = patient.exists()

    assert response.valid == False
    assert response.messages == 'There are multiple items with this name on rows 1, 2. Please remove the duplicates.'
Example #5
0
def sync_export(worksheet, users_participants, rounds_rolls, pools_titles,
                all_titles, allow_hidden):
    writer = ColWriter(users_participants)
    writer.write_header('Participants')
    sorted_participants = list(
        map(lambda x: x[1], sorted(users_participants,
                                   key=lambda x: x[0].name)))

    for participant in sorted_participants:
        writer.write_participant(participant)
    writer.next_col()

    titles = {t.id: t for t in all_titles}
    stats = {}
    for round, rolls in rounds_rolls:
        roll_by_participant_id = {r.participant_id: r for r in rolls}
        fmt = '%d.%m'
        writer.write_header(
            f'Round { round.num } ({round.start_time.strftime(fmt)}-{round.finish_time.strftime(fmt)})'
        )
        for participant in sorted_participants:
            if participant.id not in roll_by_participant_id:
                writer.write_fail()
            else:
                title = titles[roll_by_participant_id[participant.id].title_id]
                writer.write_title(title,
                                   participant.failed_round_id == round.id)

        writer.next_col()
        writer.write_header('Score')
        for participant in sorted_participants:
            score = roll_by_participant_id[
                participant.
                id].score if participant.id in roll_by_participant_id else None
            update_stats(stats, participant, score, len(rounds_rolls))
            writer.write_score(score)
        writer.next_col()

    stats = {
        k: (v[0], v[1], None if v[2] is None else v[2] / v[3])
        for k, v in stats.items()
    }
    for i, col in enumerate(['Min', 'Max', 'Avg']):
        writer.write_header(col)
        for participant in sorted_participants:
            stat = None if participant.id not in stats else stats[
                participant.id][i]
            writer.write_score(stat)
        writer.next_col()

    for pool, titles in pools_titles:
        writer.write_header(f'{ pool.name } (unused titles)')
        for title in titles:
            if not title.is_used:
                writer.write_title(title, allow_hidden=allow_hidden)
        writer.next_col()

    # Cell((0, 0)) clears the entire screen
    worksheet.update_cells([Cell((0, 0))] + writer.cells)
    worksheet.adjust_column_width(1, worksheet.cols)
Example #6
0
    def get_values(self,
                   start,
                   end,
                   returnas='matrix',
                   majdim='ROWS',
                   include_empty=True,
                   value_render=ValueRenderOption.UNFORMATTED):
        values = self.client.get_range(self.spreadsheet.id,
                                       self._get_range(start, end),
                                       majdim.upper(),
                                       value_render=value_render)
        start = format_addr(start, 'tuple')
        if not include_empty:
            matrix = values
        else:
            max_cols = len(max(values, key=len))
            matrix = [list(x + [''] * (max_cols - len(x))) for x in values]

        if returnas == 'matrix':
            return matrix
        else:
            cells = []
            for k in range(len(matrix)):
                row = []
                for i in range(len(matrix[k])):
                    if majdim == 'COLUMNS':
                        row.append(
                            Cell((start[0] + i, start[1] + k), matrix[k][i],
                                 self))
                    elif majdim == 'ROWS':
                        row.append(
                            Cell((start[0] + k, start[1] + i), matrix[k][i],
                                 self))
                    else:
                        raise InvalidArgumentValue('majdim')

                cells.append(row)
            return cells
    def update_variables(self, **kwargs):
        for var_name, var_value in kwargs.items():
            if var_name not in self.template_cells:
                continue

            template_cell = self.template_cells[var_name]
            if template_cell.direction == "fixed":
                template_cell.template_cell.value = str(var_value)
                self._cell_buffer.append(template_cell.template_cell)
            else:
                cell = Cell(tuple(template_cell.position))
                cell.value = str(var_value)

                # Update style
                if None not in template_cell.template_cell.color:
                    cell.color = template_cell.template_cell.color

                # Increase the position for the next entry of this cell
                if template_cell.direction == "row":
                    self.template_cells[var_name].inc_column()
                elif template_cell.direction == "column":
                    self.template_cells[var_name].inc_row()

                self._cell_buffer.append(cell)
Example #8
0
    def test_get_values(self):
        self.worksheet.resize(10, 10)
        self.worksheet.clear()
        self.worksheet.update_cells('A1:C2', [[1, 2, ''], [2, 3, 4]])
        assert self.worksheet.get_values('A1',
                                         'E5') == [[u'1', u'2', '', '', ''],
                                                   [u'2', u'3', u'4', '', '']]

        # @TODO not working
        # assert self.worksheet.get_values('A1','D3', returnas="cells") == [[Cell('A1', '1'), Cell('B1','2'), Cell('C1',''), Cell('D1','')],
        #                                                                   [Cell('A2','2'), Cell('B2','3'), Cell('C2','4'), Cell('D2','')]]

        assert self.worksheet.get_values(
            'A1', 'D3', returnas="cells", include_empty=False) == [[
                Cell('A1', '1'), Cell('B1', '2')
            ], [Cell('A2', '2'),
                Cell('B2', '3'),
                Cell('C2', '4')]]
        assert self.worksheet.get_values('D1',
                                         'D3',
                                         returnas="cells",
                                         include_all=True) == [[
                                             Cell('D1', '')
                                         ], [Cell('D2', '')], [Cell('D3', '')]]
Example #9
0
    def test_get_values(self):
        self.worksheet.resize(10, 10)
        self.worksheet.clear()

        assert self.worksheet.get_values('A1',
                                         'E5',
                                         include_tailing_empty=True,
                                         include_tailing_empty_rows=True)

        self.worksheet.update_values(
            'A1:D4',
            [[1, 2, '', 3], ['', '', '', ''], [4, 5, '', ''], ['', 6, '', '']])
        # matrix testing
        assert self.worksheet.get_values('A1', 'E5', include_tailing_empty=True, include_tailing_empty_rows=True) == \
               [[u'1', u'2', u'', u'3', ''], ['', '', '', '', ''], [u'4', u'5', '', '', ''], [u'', u'6', '', '', ''], ['', '', '', '', '']]
        assert self.worksheet.get_values('A1', 'E5', include_tailing_empty=True, include_tailing_empty_rows=False) == \
               [[u'1', u'2', u'', u'3', ''], ['', '', '', '', ''], [u'4', u'5', '', '', ''], [u'', u'6', '', '', ''] ]
        assert self.worksheet.get_values('A1', 'E5', include_tailing_empty=False, include_tailing_empty_rows=True) == \
               [[u'1', u'2', u'', u'3'], [], [u'4', u'5'], [u'', u'6'], []]
        assert self.worksheet.get_values('A1', 'E5', include_tailing_empty=False, include_tailing_empty_rows=False) == \
               [[u'1', u'2', u'', u'3'], [], [u'4', u'5'], [u'', u'6']]

        # matrix testing columns
        assert self.worksheet.get_values('A1', 'E5', include_tailing_empty=True, include_tailing_empty_rows=True, majdim="COLUMNS") == \
               [[u'1', u'', u'4', '', ''],[u'2', u'', u'5', u'6', ''], ['', '', '', '', ''], [u'3', '', '', '', ''], ['', '', '', '', '']]
        assert self.worksheet.get_values('A1', 'E5', include_tailing_empty=True, include_tailing_empty_rows=False, majdim="COLUMNS") == \
               [[u'1', u'', u'4', '', ''],[u'2', u'', u'5', u'6', ''], ['', '', '', '', ''], [u'3', '', '', '', '']]
        assert self.worksheet.get_values('A1', 'E5', include_tailing_empty=False, include_tailing_empty_rows=True, majdim="COLUMNS") == \
               [[u'1', u'', u'4'], [u'2', u'', u'5', u'6'], [], [u'3'], []]
        assert self.worksheet.get_values('A1', 'E5', include_tailing_empty=False, include_tailing_empty_rows=False, majdim="COLUMNS") == \
               [[u'1', u'', u'4'], [u'2', u'', u'5', u'6'], [], [u'3']]

        # Cells testing rows
        self.worksheet.clear()
        self.worksheet.update_values('A1:B2', [[1, 2], [3, '']])
        assert self.worksheet.get_values('A1', 'C3', include_tailing_empty=True, include_tailing_empty_rows=True,returnas="cells") == \
               [[Cell('A1', '1'), Cell('B1', '2'), Cell('C1', '')],
                [Cell('A2', '3'), Cell('B2', ''), Cell('C2', '')],
                [Cell('A3', ''), Cell('B3', ''), Cell('C3', '')]]
        assert self.worksheet.get_values('A1', 'C3', include_tailing_empty=True, include_tailing_empty_rows=False,returnas="cells") == \
               [[Cell('A1', '1'), Cell('B1', '2'), Cell('C1', '')],
                [Cell('A2', '3'), Cell('B2', ''), Cell('C2', '')]]
        assert self.worksheet.get_values('A1', 'C3', include_tailing_empty=False, include_tailing_empty_rows=True ,returnas="cells") == \
               [[Cell('A1', '1'), Cell('B1', '2')], [Cell('A2', '3')], []]
        assert self.worksheet.get_values('A1', 'D3', include_tailing_empty=False, include_tailing_empty_rows=False,returnas="cells" ) == \
               [[Cell('A1', '1'), Cell('B1', '2')], [Cell('A2', '3')]]

        # Cells testing cols
        self.worksheet.clear()
        self.worksheet.update_values('A1:B2', [[1, 2], [3, '']])
        assert self.worksheet.get_values('A1', 'C3', include_tailing_empty=True, include_tailing_empty_rows=True,returnas="cells",majdim="COLUMNS") == \
               [[Cell('A1', '1'), Cell('A2', '2'), Cell('A3', '')],
                [Cell('B1', '3'), Cell('B2', ''), Cell('B3', '')],
                [Cell('C1', ''), Cell('C2', ''), Cell('C3', '')]]
        assert self.worksheet.get_values('A1', 'C3', include_tailing_empty=True, include_tailing_empty_rows=False,returnas="cells",majdim="COLUMNS") == \
               [[Cell('A1', '1'), Cell('A2', '2'), Cell('A3', '')],
                [Cell('B1', '3'), Cell('B2', ''), Cell('B3', '')]]
        assert self.worksheet.get_values('A1', 'C3', include_tailing_empty=False, include_tailing_empty_rows=True ,returnas="cells",majdim="COLUMNS") == \
               [[Cell('A1', '1'), Cell('A2', '2')], [Cell('B1', '3')], []]
        assert self.worksheet.get_values('A1', 'D3', include_tailing_empty=False, include_tailing_empty_rows=False,returnas="cells",majdim="COLUMNS") == \
               [[Cell('A1', '1'), Cell('A2', '2')], [Cell('B1', '3')]]
Example #10
0
    async def on_message(self, message: Message):
        """Listener about message"""
        await self.wait_until_ready()

        content = str(message.content).lower()

        if content == 'seria update roster':
            await self.send_message(message.channel, '開始紀錄總表')
            worksheet = spreadsheet.worksheet_by_title(
                config.WorkSheetType.PlayerRoster)
            roster_matrix = worksheet.range('A3:D', returnas='matrix')

            redis_keys = redis_db.keys()
            if redis_keys:
                redis_db.delete(*redis_keys)

            with redis_db.pipeline() as pipe:
                redis_key = None
                mapping = {}
                for player_name, discord_id, character_name, job, in roster_matrix:
                    if not player_name and not character_name and not job:
                        break

                    if player_name:
                        if redis_key:
                            pipe.hmset(redis_key, mapping)

                        mapping = {}
                        redis_key = player_name
                        mapping['discord_id'] = discord_id

                    mapping[job] = character_name

                pipe.hmset(redis_key, mapping)
                pipe.execute()

            return await self.send_message(message.channel, '紀錄總表完成')
        elif content.startswith('seria anton rollcall'):
            cmd_args = content.split(' ')

            if len(cmd_args) != 5:
                await self.send_message(message.channel, '指令錯誤')
                return

            weekday, group_number = cmd_args[3], int(cmd_args[4])
            weekday_mapping = {
                'wed': config.WorkSheetType.AntonRaidWed,
                'sat': config.WorkSheetType.AntonRaidSat,
                'sun': config.WorkSheetType.AntonRaidSun
            }
            if weekday not in weekday_mapping and not (1 <= group_number <=
                                                       16):
                await self.send_message(message.channel, '指令錯誤')
                return

            _, _, group_cell_range = config.GROUP_INFO_SEQUENCE[group_number -
                                                                1]

            msg = f'{group_number} 團該集合囉!\n\n'
            antion_raid_worksheet = spreadsheet.worksheet_by_title(
                weekday_mapping[weekday])
            group_matrix = antion_raid_worksheet.range(group_cell_range,
                                                       returnas='matrix')

            for team_index, team in enumerate(group_matrix, start=1):
                msg += f'{team_index} 隊:\n'
                for player_with_job in team:

                    if not player_with_job:
                        continue

                    prog = player_with_job_pattern.match(player_with_job)
                    if prog is None:
                        msg += f'{player_with_job} <-- 文字分析錯誤\n'
                        continue

                    matched_keyword_mapping = prog.groupdict()
                    player = matched_keyword_mapping['player']
                    job = matched_keyword_mapping['job']
                    discord_id = redis_db.hget(player, 'discord_id')
                    character_name = redis_db.hget(player, job)

                    member = self.discord_server.get_member(discord_id)
                    player = member.mention if member is not None else player

                    if character_name:
                        msg += f'{character_name}({job}) cc {player}\n'
                    else:
                        msg += f'{character_name}({job}) cc {player} <-- 您的出戰角色於總表查無資料,請於總表修正,謝謝\n'
                msg += '\n'

            await self.send_message(message.channel, msg)
            return await self.change_presence(game=Game(
                name=f'Anton {group_number} 團,出征!'))
        elif content.startswith('seria status reset'):
            await self.change_presence()
            return
        elif content.startswith('seria anton check'):
            cmd_args = content.split(' ')

            if len(cmd_args) != 4:
                return await self.send_message(message.channel, '指令錯誤')

            weekday = cmd_args[3]
            weekday_mapping = {
                'wed': config.WorkSheetType.AntonRaidWed,
                'sat': config.WorkSheetType.AntonRaidSat,
                'sun': config.WorkSheetType.AntonRaidSun
            }
            if weekday not in weekday_mapping:
                return await self.send_message(message.channel, '指令錯誤')

            worksheet_title = weekday_mapping[weekday]
            await self.send_message(message.channel,
                                    f'檢查 {worksheet_title} 的團表')

            antion_raid_worksheet = spreadsheet.worksheet_by_title(
                worksheet_title)

            YELLOW = (1, 1, 0, 0)

            player_with_job_list = []
            player_with_job_error_list = []
            group_error_collection = {}
            for group_number, group_number_cell_pos, group_cell_range in config.GROUP_INFO_SEQUENCE:

                group_number_cell = Cell(group_number_cell_pos,
                                         worksheet=antion_raid_worksheet)
                if group_number_cell.color != YELLOW:
                    break

                player_list = []
                player_error_list = []
                group = antion_raid_worksheet.range(group_cell_range,
                                                    returnas='matrix')
                for team in group:
                    for player_with_job in team:

                        if not player_with_job:
                            continue

                        if player_with_job in player_with_job_list:
                            player_with_job_error_list.append(player_with_job)
                        else:
                            player_with_job_list.append(player_with_job)

                        prog = player_with_job_pattern.match(player_with_job)
                        if prog is None:
                            continue

                        matched_keyword_mapping = prog.groupdict()
                        player = matched_keyword_mapping['player']

                        if player in player_list:
                            player_error_list.append(player)
                        else:
                            player_list.append(player)

                    if player_error_list:
                        group_error_collection[
                            group_number] = player_error_list

            if player_with_job_error_list or group_error_collection:
                msg = ''
                if player_with_job_error_list:
                    player_with_job_error_list = ', '.join(
                        player_with_job_error_list)
                    msg += f'* 總表重複人物: {player_with_job_error_list}\n'

                if group_error_collection:
                    for group_number, players in group_error_collection.items(
                    ):
                        players = ', '.join(players)
                        msg += f'* {group_number} 團表重複人物: {players}\n'
                return await self.send_message(message.channel, msg)
            else:
                return await self.send_message(message.channel,
                                               '沒有任何重複安排的人員唷~! :heart:')
Example #11
0
 def new_cell(self, value):
     return Cell((self.row + 1, self.col + 1), value)