Exemple #1
0
 def __init__(self,
              block,
              text=None,
              fold_level=None,
              def_type=None,
              def_name=None,
              color=None):
     """
     Args:
         text (str)
         fold_level (int)
         def_type (int): [CLASS, FUNCTION, STATEMENT, COMMENT, CELL]
         def_name (str)
         color (PyQt.QtGui.QTextCharFormat)
     """
     super(OutlineExplorerData, self).__init__()
     self.text = text
     self.fold_level = fold_level
     self.def_type = def_type
     self.def_name = def_name
     self.color = color
     if running_under_pytest():
         # block might be a dummy
         self.block = block
     else:
         # Copy the text block to make sure it is not deleted
         self.block = QTextBlock(block)
Exemple #2
0
class OutlineExplorerData(QObject):
    CLASS, FUNCTION, STATEMENT, COMMENT, CELL = list(range(5))
    FUNCTION_TOKEN = 'def'
    CLASS_TOKEN = 'class'

    # Emitted if the OutlineExplorerData was changed
    sig_update = Signal()

    def __init__(self,
                 block,
                 text=None,
                 fold_level=None,
                 def_type=None,
                 def_name=None,
                 color=None):
        """
        Args:
            text (str)
            fold_level (int)
            def_type (int): [CLASS, FUNCTION, STATEMENT, COMMENT, CELL]
            def_name (str)
            color (PyQt.QtGui.QTextCharFormat)
        """
        super(OutlineExplorerData, self).__init__()
        self.text = text
        self.fold_level = fold_level
        self.def_type = def_type
        self.def_name = def_name
        self.color = color
        if running_under_pytest():
            # block might be a dummy
            self.block = block
        else:
            # Copy the text block to make sure it is not deleted
            self.block = QTextBlock(block)

    def is_not_class_nor_function(self):
        return self.def_type not in (self.CLASS, self.FUNCTION)

    def is_class_or_function(self):
        return self.def_type in (self.CLASS, self.FUNCTION)

    def is_comment(self):
        return self.def_type in (self.COMMENT, self.CELL)

    def get_class_name(self):
        if self.def_type == self.CLASS:
            return self.def_name

    def get_function_name(self):
        if self.def_type == self.FUNCTION:
            return self.def_name

    def get_token(self):
        if self.def_type == self.FUNCTION:
            token = self.FUNCTION_TOKEN
        elif self.def_type == self.CLASS:
            token = self.CLASS_TOKEN

        return token

    @property
    def def_name(self):
        """Get the cell name."""
        # Non cell don't need unique names.
        if self.def_type != self.CELL:
            return self._def_name

        def get_name(oedata):
            name = oedata._def_name
            if not name:
                name = _('Unnamed Cell')
            return name

        self_name = get_name(self)

        existing_numbers = []

        def check_match(oedata):
            # Look for "string"
            other_name = get_name(oedata)
            pattern = '^' + re.escape(self_name) + r'(?:, #(\d+))?$'
            match = re.match(pattern, other_name)
            if match:
                # Check if already has a number
                number = match.groups()[0]
                if number:
                    existing_numbers.append(int(number))
                return True
            return False

        # Count cells
        N_prev = 0
        for oedata in document_cells(self.block, forward=False):
            if check_match(oedata):
                N_prev += 1
        N_fix_previous = len(existing_numbers)

        N_next = 0
        for oedata in document_cells(self.block, forward=True):
            if check_match(oedata):
                N_next += 1

        # Get the remaining indexeswe can use
        free_indexes = [
            idx for idx in range(N_prev + N_next + 1)
            if idx + 1 not in existing_numbers
        ]

        idx = free_indexes[N_prev - N_fix_previous]

        if N_prev + N_next > 0:
            return self_name + ', #{}'.format(idx + 1)

        return self_name

    @def_name.setter
    def def_name(self, value):
        """Set name."""
        self._def_name = value

    def update(self, other):
        """Try to update to avoid reloading everything."""
        if (self.def_type == other.def_type
                and self.fold_level == other.fold_level):
            self.text = other.text
            old_def_name = self._def_name
            self._def_name = other._def_name
            self.color = other.color
            self.sig_update.emit()
            if self.def_type == self.CELL:
                if self.cell_level != other.cell_level:
                    return False
                # Must update all other cells whose name has changed.
                for oedata in document_cells(self.block, forward=True):
                    if oedata._def_name in [self._def_name, old_def_name]:
                        oedata.sig_update.emit()
            return True
        return False

    def is_valid(self):
        """Check if the oedata has a valid block attached."""
        block = self.block
        return (block and block.isValid() and block.userData()
                and hasattr(block.userData(), 'oedata')
                and block.userData().oedata == self)

    def has_name(self):
        """Check if cell has a name."""
        if self._def_name:
            return True
        else:
            return False

    def get_block_number(self):
        """Get the block number."""
        if not self.is_valid():
            # Avoid calling blockNumber if not a valid block
            return None
        return self.block.blockNumber()