def __init__(self, dimension, level, hide,
            width, location, targetlabel, mode, formula, cellformat, decimals,
            printlabels, floatfail, custommodule, align, repeatloc):
        """location is a sequence of targe locations to modify or insert.
        It can include positive or negative numbers (or things that can be converted to these) and
        strings that will be matched to the lowest level of the column labels ignoring case.
        If dimension == 'rows' then rows are processed instead of columns.
        'rows' cannot be combined with 'width'
        level specifies which level to check.  -1 is the innermost.  This only affects the behavior
        when using specific labels.
        width is a sequence that specifies the width in points
        to be applied to the specified columns.
        secondary will be created as None or secondary table object
        '"""

        attributesFromDict(locals())  # copy parameters

        if not _isseq(location):
            raise ValueError(_("Target specification must be a sequence of one or more values"))
        if width:
            if dimension == 'rows':
                raise ValueError(_("The rows dimension cannot be combined with resizing"))

        self.formula = Formula(formula, targetlabel, cellformat, decimals, hide, width, floatfail, 
            custommodule, align)
def cleansubtypes(subtype):
    """Regularize subtype specification and return as list"""
    
    if subtype is None:
        return [None]
    if not _isseq(subtype):
        subtype=[subtype]
    # remove white space
    subtype = ["".join(st.lower().split()) for st in subtype]
    # remove matching outer quotes of any type
    subtype = [re.sub(r"""^('|")(.*)\1$""", r"""\2""", st) for st in subtype]
    if "*" in subtype:
        subtype = ["*"]
    return subtype
 def addrow(self, rowlabel=None, cvalues=None):
     """Append a row labelled rowlabel to the table and set value(s) from cvalues.
     
     rowlabel is a label for the stub.
     cvalues is a sequence of values with the same number of values are there are columns in the table."""
         
     if cvalues is None:
         cvalues = []
     self.rowcount += 1
     if rowlabel is None:
             self.rowlabels.append(str(self.rowcount))
     else:
             self.rowlabels.append(rowlabel)
     if not _isseq(cvalues):
             cvalues = [cvalues]
     self.columnvalues.extend(cvalues)
 def addrow(self, rowlabel=None, cvalues=None):
     """Append a row labelled rowlabel to the table and set value(s) from cvalues.
     
     rowlabel is a label for the stub.
     cvalues is a sequence of values with the same number of values are there are columns in the table."""
         
     if cvalues is None:
         cvalues = []
     self.rowcount += 1
     if rowlabel is None:
             self.rowlabels.append(str(self.rowcount))
     else:
             self.rowlabels.append(rowlabel)
     if not _isseq(cvalues):
             cvalues = [cvalues]
     self.columnvalues.extend(cvalues)
def modify(subtype, select=None,  skiplog=True, process="preceding", dimension='columns',
           level=-1, hide=False, widths=None, rowlabels=None, rowlabelwidths=None,
           textstyle=None, textcolor=None, bgcolor=None, applyto="both", customfunction=None, 
           printlabels=False, regexp=False, tlook=None, countinvis=True,
           sigcells=None, siglevels="both"):
    """Apply a hide or show action to specified columns or rows of the specified subtype or resize columns

    subtype is the OMS subtype of the tables to process or a sequence of subtypes
    select is a sequence of column or row identifiers or ["ALL"].  Identifiers can be
    positive or negative numbers, counting from 0.  Negative numbers count from
    the end: -1 is the last row or column.
    Identifiers can also be the text of the lowest level in the column heading.
    If the value is or can be converted to an integer, it is assumed to be a column number.
    Numeric values are truncated to integers.
    You cannot hide all the items even though this routine will try.
    process specifies "preceding" to process the output of the preceding command or "all"
    to process all tables having any of the specified subtypes.
    level defaults to the innermost level (-1).  Specify a more negative number to move out or up in
    the label array.  -2, for example, would be the next-to-innermost level.
    When counting columns or rows, count at the innermost level regardless of the level setting.
    Hide cannot be combined with other actions.
    if skiplog is True, if the last item in the Viewer is a log, the search starts with the preceding item.
    It needs to be True if this function is run from the extension command and commands are echoing to the log.
    dimension == 'columns' indicates that columns should be operated on.  dimension == 'rows' specifies rows.
    widths specifies the width or widths to be applied to the selected rows or columns
    If it is a single element, it is used for all specified columns.
    Otherwise, it is a sequence of sizes in points of the same length as the select list.
    rowlabels and rowlabelwidths can be specified to set stub (row) widths.  rowlabels can only contain numbers.
    textstyle, textcolor, and bgcolor apply formatting.  colors are specified as three integers for RGB.
    textstyle can be REGULAR, BOLD, ITALIC, or BOLDITALIC
    APPLYTO can be BOTH, DATACELLS, LABELS, or a Boolean Python expression in which x stands for
    the cell value.

    customfunction is a list of module.function names of  functions to be called as cells are styled.

    This function processes the latest item in the designated Viewer: all pivot tables for that instance of
    the procedure are processed according to the subtype specification.
"""
    # ensure localization function is defined
    # pot file must be named SPSSINC_MODIFY_TABLES.pot
    global _
    try:
        _("---")
    except:
        def _(msg):
            return msg
        ###debugging
    #try:
        #import wingdbstub
        #if wingdbstub.debugger != None:
            #import time
            #wingdbstub.debugger.StopDebug()
            #time.sleep(2)
            #wingdbstub.debugger.StartDebug()
        #import thread
        #wingdbstub.debugger.SetDebugThreads({thread.get_ident(): 1}, default_policy=0)
    #except:
        #pass
    SpssClient.StartClient()
    try:
        info = NonProcPivotTable("INFORMATION", tabletitle=_("Information"))
        c = PtColumns(select, dimension, level, hide, widths, 
            rowlabels, rowlabelwidths, textstyle, textcolor, bgcolor, applyto, customfunction, 
            printlabels,regexp, tlook,
            sigcells, siglevels)
        
        if sigcells is not None and not v24ok:
            raise ValueError(_("""Significance highlighting requires at least Statistics version 24"""))

        if not _isseq(subtype):
            subtype=[subtype]
        # remove white space
        subtype = ["".join(st.lower().split()) for st in subtype]
        # remove matching outer quotes of any type
        subtype = [re.sub(r"""^('|")(.*)\1$""", r"""\2""", st) for st in subtype]
        if "*" in subtype:
            subtype = ["*"]
        items = SpssClient.GetDesignatedOutputDoc().GetOutputItems()
        itemcount = items.Size()
        if skiplog and items.GetItemAt(itemcount-1).GetType() == SpssClient.OutputItemType.LOG:
            itemcount -= 1
        for itemnumber in range(itemcount-1, -1, -1):
            item = items.GetItemAt(itemnumber)
            if process == "preceding" and item.GetTreeLevel() <= 1:
                break
            if item.GetType() == SpssClient.OutputItemType.PIVOT and\
               (subtype[0] == "*" or "".join(item.GetSubType().lower().split()) in subtype):
                c.thetable = item.GetSpecificType()
                if not countinvis:
                    set23(c.thetable)
                c.applyaction(c.thetable, info) 
    finally:
        info.generate()
        SpssClient.StopClient()
    def __init__(self, columns, dimension, level, hide,
                 widths, rowlabels, rowlabelwidths, textstyle, textcolor, bgcolor, applyto, customfunction, 
                 printlabels, regexp, tlook,
                 sigcells, siglevels):
        """columns is a sequence of identifiers of columns to act on.
        It can include positive or negative numbers (or things that can be converted to these) and
        strings that will be matched to the lowest level of the column labels ignoring case.
        Use "<<ALL>>" to refer to all columns - not valid for hide.
        action is 'hide', 'show', or 'resize'
        If action == 'resize', widths must be specified.
        If dimension == 'rows' then rows are processed instead of columns.
        'rows' cannot be combined with 'resize'
        level specifies which level to check.  -1 is the innermost.  This only affects the behavior
        when using specific labels.
        widths is only used with action == 'resize'.  It is a sequence that specifies the width 
        or widths to be applied to the specified columns.  
        If it is a sequence of length 1, it is used for all specified columns.
        Otherwise, it is a sequence of sizes in points of the same length as the columns list.
        if regexp, nonnumerical text in columns is treated as a regular expression
        sigcells indicates whether to flag significant cells (V24+, CTABLES standard markers only)
        siglevels indicates which levels to flag in case there are two
        '"""

        if columns is None:
            columns = []
        attributesFromDict(locals())  # copy parameters
        self.encoding = locale.getlocale()[1]
        self.actionset = any([widths, rowlabelwidths, textstyle, textcolor, bgcolor, customfunction])
        if hide and self.actionset:
            raise ValueError(_("HIDE cannot be combined with other actions"))
        if  not (self.actionset or self.tlook):
            self.hide = True

        if not _isseq(columns):
            raise ValueError(_("Row or column specification must be a sequence of one or more values"))
        if widths:
            if dimension == 'rows':
                raise ValueError(_("The rows dimension cannot be combined with resizing"))
            if len(widths) == 1:
                self.widths = len(columns) * widths  # The <<ALL>> case is handled specially later
            if regexp and len(widths) > 0:
                raise ValueError(_("Regular expression mode is not available with widths"))
            if  len(columns) != len(self.widths):
                raise ValueError(_("The number of column sizes specified is different from number of columns specified."))
        rlgiven = rowlabels is not None
        rlwgiven = rowlabelwidths is not None
        if rlgiven ^ rlwgiven:
            raise ValueError(_("ROWLABELS and ROWLABELWIDTHS must be specified together"))
        if rowlabels:
            if len(rowlabelwidths) == 1:
                self.rowlabelwidths = len(rowlabels) * rowlabelwidths
            if  len(rowlabelwidths) != len(rowlabels):
                raise ValueError(_("The number of row label sizes specified is different from number of row labels specified."))
        else:
            if not columns:
                raise ValueError(_("SELECT is required unless ROWLABELS is specified"))
        self.columns = []
        regexplist = []
        for item in columns:
            try:
                self.columns.append(int(item))  # add all integer-like items to list
            except:
                # accumulate regexp text and regular text separately but <<ALL>> is special
                # self.regexp will be the compiled reg expression or False if no expressions or option is False
                if regexp and not columns[0] == "<<ALL>>":
                    regexplist.append(item)
                else:
                    self.columns.append(item)
        if regexplist:   # combine all regexp terms with or if any were found
            try:
                regexp = "|".join(["("+item+")" for item in regexplist])
                self.regexp = re.compile(regexp, re.LOCALE)
            except:
                reerr = sys.exc_info()[1]
                raise ValueError(_("Invalid regular expression: %s error: %s") % (regexp, str(reerr)))
        else:
            self.regexp = False
        if columns and columns[0] == "<<ALL>>" and hide:
            raise ValueError(_("HIDE cannot be applied with columns = <<ALL>>"))
        self.actionlist = [self.widths, self.rowlabelwidths, self.textstyle, self,textcolor, self.bgcolor]

        # build style code as a list of functions to call with user specifications
        # some parameters in the stock function signature are ignored in order to have
        # uniformity with the custom function

        if self.applyto.lower() in ["both", "labels", "datacells"]:
            self.applyto = self.applyto.lower()
        self.stylecalls = []
        if self.textstyle:
            def f(obj, row, column, numrows, numcols, section, ignore):
                obj.SetTextStyleAt(row, column, PtColumns.textstyles[self.textstyle])
            self.stylecalls.append(f)
        if self.textcolor:
            self.textcolor = RGB(self.textcolor)
            def f(obj, row, column, numrows, numcols, section, ignore):
                obj.SetTextColorAt(row, column, self.textcolor)
            self.stylecalls.append(f)
        if self.bgcolor:
            self.bgcolor = RGB(self.bgcolor)
            def f(obj, row, column, numrows, numcols, section, ignore):
                try:
                    obj.SetBackgroundColorAt(row, column, self.bgcolor)
                except:
                    raise SystemError(_("Set Background Color exception: %s %s %s") %(row, column, section))
            self.stylecalls.append(f)
        if not self.customfunction is None:
            for f in self.customfunction:
                self.stylecalls.append(resolvestr(f))
        self.previousUsedValue = ""
        
        # significance controls
        self.sigsetup(self.sigcells)
def modify(subtype, select=None,  skiplog=True, process="preceding", dimension='columns',
           level=-1, hide=False, widths=None, rowlabels=None, rowlabelwidths=None,
           textstyle=None, textcolor=None, bgcolor=None, applyto="both", customfunction=None, 
           printlabels=False, regexp=False, tlook=None, countinvis=True,
           sigcells=None, siglevels="both"):
    """Apply a hide or show action to specified columns or rows of the specified subtype or resize columns

    subtype is the OMS subtype of the tables to process or a sequence of subtypes
    select is a sequence of column or row identifiers or ["ALL"].  Identifiers can be
    positive or negative numbers, counting from 0.  Negative numbers count from
    the end: -1 is the last row or column.
    Identifiers can also be the text of the lowest level in the column heading.
    If the value is or can be converted to an integer, it is assumed to be a column number.
    Numeric values are truncated to integers.
    You cannot hide all the items even though this routine will try.
    process specifies "preceding" to process the output of the preceding command or "all"
    to process all tables having any of the specified subtypes.
    level defaults to the innermost level (-1).  Specify a more negative number to move out or up in
    the label array.  -2, for example, would be the next-to-innermost level.
    When counting columns or rows, count at the innermost level regardless of the level setting.
    Hide cannot be combined with other actions.
    if skiplog is True, if the last item in the Viewer is a log, the search starts with the preceding item.
    It needs to be True if this function is run from the extension command and commands are echoing to the log.
    dimension == 'columns' indicates that columns should be operated on.  dimension == 'rows' specifies rows.
    widths specifies the width or widths to be applied to the selected rows or columns
    If it is a single element, it is used for all specified columns.
    Otherwise, it is a sequence of sizes in points of the same length as the select list.
    rowlabels and rowlabelwidths can be specified to set stub (row) widths.  rowlabels can only contain numbers.
    textstyle, textcolor, and bgcolor apply formatting.  colors are specified as three integers for RGB.
    textstyle can be REGULAR, BOLD, ITALIC, or BOLDITALIC
    APPLYTO can be BOTH, DATACELLS, LABELS, or a Boolean Python expression in which x stands for
    the cell value.

    customfunction is a list of module.function names of  functions to be called as cells are styled.

    This function processes the latest item in the designated Viewer: all pivot tables for that instance of
    the procedure are processed according to the subtype specification.
"""
    # ensure localization function is defined
    # pot file must be named SPSSINC_MODIFY_TABLES.pot
    global _
    try:
        _("---")
    except:
        def _(msg):
            return msg
        ###debugging
    #try:
        #import wingdbstub
        #if wingdbstub.debugger != None:
            #import time
            #wingdbstub.debugger.StopDebug()
            #time.sleep(2)
            #wingdbstub.debugger.StartDebug()
        #import thread
        #wingdbstub.debugger.SetDebugThreads({thread.get_ident(): 1}, default_policy=0)
    #except:
        #pass
    SpssClient.StartClient()
    try:
        info = NonProcPivotTable("INFORMATION", tabletitle=_("Information"))
        c = PtColumns(select, dimension, level, hide, widths, 
            rowlabels, rowlabelwidths, textstyle, textcolor, bgcolor, applyto, customfunction, 
            printlabels,regexp, tlook,
            sigcells, siglevels)
        
        if sigcells is not None and not v24ok:
            raise ValueError(_("""Significance highlighting requires at least Statistics version 24"""))

        if not _isseq(subtype):
            subtype=[subtype]
        # remove white space
        subtype = ["".join(st.lower().split()) for st in subtype]
        # remove matching outer quotes of any type
        subtype = [re.sub(r"""^('|")(.*)\1$""", r"""\2""", st) for st in subtype]
        if "*" in subtype:
            subtype = ["*"]
        items = SpssClient.GetDesignatedOutputDoc().GetOutputItems()
        itemcount = items.Size()
        if skiplog and items.GetItemAt(itemcount-1).GetType() == SpssClient.OutputItemType.LOG:
            itemcount -= 1
        for itemnumber in range(itemcount-1, -1, -1):
            item = items.GetItemAt(itemnumber)
            if process == "preceding" and item.GetTreeLevel() <= 1:
                break
            if item.GetType() == SpssClient.OutputItemType.PIVOT and\
               (subtype[0] == "*" or "".join(item.GetSubType().lower().split()) in subtype):
                c.thetable = item.GetSpecificType()
                if not countinvis:
                    set23(c.thetable)
                c.applyaction(c.thetable, info) 
    finally:
        info.generate()
        SpssClient.StopClient()
    def __init__(self, columns, dimension, level, hide,
                 widths, rowlabels, rowlabelwidths, textstyle, textcolor, bgcolor, applyto, customfunction, 
                 printlabels, regexp, tlook,
                 sigcells, siglevels):
        """columns is a sequence of identifiers of columns to act on.
        It can include positive or negative numbers (or things that can be converted to these) and
        strings that will be matched to the lowest level of the column labels ignoring case.
        Use "<<ALL>>" to refer to all columns - not valid for hide.
        action is 'hide', 'show', or 'resize'
        If action == 'resize', widths must be specified.
        If dimension == 'rows' then rows are processed instead of columns.
        'rows' cannot be combined with 'resize'
        level specifies which level to check.  -1 is the innermost.  This only affects the behavior
        when using specific labels.
        widths is only used with action == 'resize'.  It is a sequence that specifies the width 
        or widths to be applied to the specified columns.  
        If it is a sequence of length 1, it is used for all specified columns.
        Otherwise, it is a sequence of sizes in points of the same length as the columns list.
        if regexp, nonnumerical text in columns is treated as a regular expression
        sigcells indicates whether to flag significant cells (V24+, CTABLES standard markers only)
        siglevels indicates which levels to flag in case there are two
        '"""

        if columns is None:
            columns = []
        attributesFromDict(locals())  # copy parameters
        self.encoding = locale.getlocale()[1]
        self.actionset = any([widths, rowlabelwidths, textstyle, textcolor, bgcolor, customfunction])
        if hide and self.actionset:
            raise ValueError(_("HIDE cannot be combined with other actions"))
        if  not (self.actionset or self.tlook):
            self.hide = True

        if not _isseq(columns):
            raise ValueError(_("Row or column specification must be a sequence of one or more values"))
        if widths:
            if dimension == 'rows':
                raise ValueError(_("The rows dimension cannot be combined with resizing"))
            if len(widths) == 1:
                self.widths = len(columns) * widths  # The <<ALL>> case is handled specially later
            if regexp and len(widths) > 0:
                raise ValueError(_("Regular expression mode is not available with widths"))
            if  len(columns) != len(self.widths):
                raise ValueError(_("The number of column sizes specified is different from number of columns specified."))
        rlgiven = rowlabels is not None
        rlwgiven = rowlabelwidths is not None
        if rlgiven ^ rlwgiven:
            raise ValueError(_("ROWLABELS and ROWLABELWIDTHS must be specified together"))
        if rowlabels:
            if len(rowlabelwidths) == 1:
                self.rowlabelwidths = len(rowlabels) * rowlabelwidths
            if  len(rowlabelwidths) != len(rowlabels):
                raise ValueError(_("The number of row label sizes specified is different from number of row labels specified."))
        else:
            if not columns:
                raise ValueError(_("SELECT is required unless ROWLABELS is specified"))
        self.columns = []
        regexplist = []
        for item in columns:
            try:
                self.columns.append(int(item))  # add all integer-like items to list
            except:
                # accumulate regexp text and regular text separately but <<ALL>> is special
                # self.regexp will be the compiled reg expression or False if no expressions or option is False
                if regexp and not columns[0] == "<<ALL>>":
                    regexplist.append(item)
                else:
                    self.columns.append(item)
        if regexplist:   # combine all regexp terms with or if any were found
            try:
                regexp = "|".join(["("+item+")" for item in regexplist])
                self.regexp = re.compile(regexp, re.LOCALE)
            except:
                reerr = sys.exc_info()[1]
                raise ValueError(_("Invalid regular expression: %s error: %s") % (regexp, str(reerr)))
        else:
            self.regexp = False
        if columns and columns[0] == "<<ALL>>" and hide:
            raise ValueError(_("HIDE cannot be applied with columns = <<ALL>>"))
        self.actionlist = [self.widths, self.rowlabelwidths, self.textstyle, self,textcolor, self.bgcolor]

        # build style code as a list of functions to call with user specifications
        # some parameters in the stock function signature are ignored in order to have
        # uniformity with the custom function

        if self.applyto.lower() in ["both", "labels", "datacells"]:
            self.applyto = self.applyto.lower()
        self.stylecalls = []
        if self.textstyle:
            def f(obj, row, column, numrows, numcols, section, ignore):
                obj.SetTextStyleAt(row, column, PtColumns.textstyles[self.textstyle])
            self.stylecalls.append(f)
        if self.textcolor:
            self.textcolor = RGB(self.textcolor)
            def f(obj, row, column, numrows, numcols, section, ignore):
                obj.SetTextColorAt(row, column, self.textcolor)
            self.stylecalls.append(f)
        if self.bgcolor:
            self.bgcolor = RGB(self.bgcolor)
            def f(obj, row, column, numrows, numcols, section, ignore):
                try:
                    obj.SetBackgroundColorAt(row, column, self.bgcolor)
                except:
                    raise SystemError(_("Set Background Color exception: %s %s %s") %(row, column, section))
            self.stylecalls.append(f)
        if not self.customfunction is None:
            for f in self.customfunction:
                self.stylecalls.append(resolvestr(f))
        self.previousUsedValue = ""
        
        # significance controls
        self.sigsetup(self.sigcells)