Exemple #1
0
def _check_index(value: int, length: int, bound: bool) -> int:
    if not isinstance(value, int):
        raise GridIndexError('Indices must be integers, found {}.'.format(value))
    if value < 0:
        value = value + length
    if value < 0 + bound or value >= length + bound:
        raise GridIndexError('Index out of range.')
    return value
Exemple #2
0
    def _key_to_rows_columns(self, key: Any) -> Tuple[int, int, int, int]:
        # TODO spaghetti code cleanup needed!
        if isinstance(key, tuple):
            if len(key) == 1:
                rows_cols = self._key_to_rows_columns(key[0])
            else:
                try:
                    row_key, column_key = key
                except ValueError:
                    raise GridIndexError(
                        'Index must be 1 or 2 values, found {}'.format(key))
                if isinstance(row_key, int):
                    row_start = _check_index(row_key, len(self.rows), False)
                    row_end = row_start + 1
                elif isinstance(row_key, slice):
                    row_start, row_end = _slice_to_start_end(
                        row_key, len(self.rows))
                    row_start = _check_index(row_start, len(self.rows), False)
                    row_end = _check_index(row_end, len(self.rows), True)
                else:
                    raise GridIndexError(
                        'Cannot index with {}, pass in a int or a slice.'.
                        format(row_key))

                if isinstance(column_key, int):
                    column_start = _check_index(column_key, len(self.columns),
                                                False)
                    column_end = column_start + 1
                elif isinstance(column_key, slice):
                    column_start, column_end = _slice_to_start_end(
                        column_key, len(self.columns))
                    column_start = _check_index(column_start,
                                                len(self.columns), False)
                    column_end = _check_index(column_end, len(self.columns),
                                              True)
                else:
                    raise GridIndexError(
                        'Cannot index with {}, pass in a int or a slice.'.
                        format(column_key))
                rows_cols = row_start, column_start, row_end, column_end

        elif isinstance(key, slice):
            start, end = _slice_to_start_end(key, len(self.rows))
            start = _check_index(start, len(self.rows), False)
            end = _check_index(end, len(self.rows), True)
            rows_cols = start, 0, end, len(self.columns)
        elif isinstance(key, int):
            row_start = _check_index(key, len(self.rows), False)
            rows_cols = row_start, 0, row_start + 1, len(self.columns)
        else:
            raise GridIndexError('Invalid index {}'.format(key))
        return rows_cols
Exemple #3
0
    def __setitem__(self, key, widget):
        """Add widget to the view."""
        if isinstance(key, tuple):
            if len(key) == 1:
                self[key[0]] = widget
            else:
                try:
                    row_key, column_key = key
                except ValueError:
                    raise GridIndexError('Index must be 1 or 2 values, found {}'.format(key))
                if isinstance(row_key, int):
                    row_start = row_key
                    row_end = None
                elif isinstance(row_key, slice):
                    row_start, row_end = _slice_to_start_end(row_key, len(self.rows))
                else:
                    raise GridIndexError(
                        'Cannot index with {}, pass in a int or a slice.'.format(row_key)
                    )

                if isinstance(column_key, int):
                    column_start = column_key
                    column_end = None
                elif isinstance(column_key, slice):
                    column_start, column_end = _slice_to_start_end(column_key, len(self.columns))
                else:
                    raise GridIndexError(
                        'Cannot index with {}, pass in a int or a slice.'.format(column_key)
                    )
                self._add(
                    widget, row_start=row_start, column_start=column_start,
                    row_end=row_end, column_end=column_end
                )

        elif isinstance(key, slice):
            start, end = _slice_to_start_end(key, len(self.rows))
            self._add(
                widget, row_start=start, column_start=0,
                row_end=end, column_end=len(self.columns)
            )
        elif isinstance(key, int):
            self._add(widget, row_start=key, column_start=0, column_end=len(self.columns))
        else:
            raise GridIndexError('Invalid index {}'.format(key))
Exemple #4
0
def _slice_to_start_end(slc: slice, length: int) -> Tuple[int, int]:
    if slc.step is not None and slc.step != 1:
        raise GridIndexError(
            'slice step is not supported must be None or 1, was {}'.format(slc.step)
        )

    start = 0
    if slc.start is not None:
        start = slc.start

    end = length
    if slc.stop is not None:
        end = slc.stop
    return start, end
Exemple #5
0
    def _add(self, widget: Component, row_start: Optional[int] = None,
             column_start: Optional[int] = None, row_end: Optional[int] = None,
             column_end: Optional[int] = None) -> None:
        """Add a widget to the grid.

        Zero-based index and exclusive.

        Parameters
        ----------
        widget : bowtie._Component
            A Bowtie widget instance.
        row_start : int, optional
            Starting row for the widget.
        column_start : int, optional
            Starting column for the widget.
        row_end : int, optional
            Ending row for the widget.
        column_end : int, optional
            Ending column for the widget.

        """
        if not isinstance(widget, Component):
            raise ValueError('Widget must be a type of Component, found {}'.format(type(widget)))

        if row_start is not None and row_end is not None and row_start >= row_end:
            raise GridIndexError('row_start: {} must be less than row_end: {}'
                                 .format(row_start, row_end))
        if column_start is not None and column_end is not None and column_start >= column_end:
            raise GridIndexError('column_start: {} must be less than column_end: {}'
                                 .format(column_start, column_end))

        # pylint: disable=protected-access
        if widget._PACKAGE:
            self.packages.add(widget._PACKAGE)
        self.templates.add(widget._TEMPLATE)
        self.imports.add(_Import(component=widget._COMPONENT,
                                 module=widget._TEMPLATE[:widget._TEMPLATE.find('.')]))

        used_msg = 'Cell at [{}, {}] is already used.'
        if row_start is None or column_start is None:
            if row_start is not None:
                raise MissingRowOrColumn(
                    'Only row_start was defined. '
                    'Please specify both column_start and row_start or neither.'
                )
            if column_start is not None:
                raise MissingRowOrColumn(
                    'Only column_start was defined. '
                    'Please specify both column_start and row_start or neither.'
                )
            if row_end is not None or column_end is not None:
                raise MissingRowOrColumn(
                    'If you specify an end index you must '
                    'specify both row_start and column_start.'
                )
            row, col = None, None
            for (row, col), use in self.used.items():
                if not use:
                    break
            else:
                raise NoUnusedCellsError()
            span = Span(row, col)
            self.used[row, col] = True
        elif row_end is None and column_end is None:
            if self.used[row_start, column_start]:
                raise UsedCellsError(used_msg.format(row_start, column_start))
            span = Span(row_start, column_start)
            self.used[row_start, column_start] = True
        else:
            if row_end is None:
                row_end = row_start + 1
            if column_end is None:
                column_end = column_start + 1

            for row, col in product(range(row_start, row_end),
                                    range(column_start, column_end)):
                if self.used[row, col]:
                    raise UsedCellsError(used_msg.format(row, col))

            for row, col in product(range(row_start, row_end),
                                    range(column_start, column_end)):
                self.used[row, col] = True
            span = Span(row_start, column_start, row_end, column_end)

        self.spans[span].append(widget)