(self, item_path, item_doc_type, column_transform)
return None, None
Given a path and transform, will return the column and its index. If not found, will
        return None, None.

        :param item_path: A list of path nodes that identify a column
        :param item_doc_type: The doc type of the item (often just ExportItem). If getting
                UserDefinedExportColumn, set this to None
        :param column_transform: A transform that is applied on the column
        :returns index, column: The index of the column in the list and an ExportColumn
Given a path and transform, will return the column and its index. If not found, will
        return None, None.
Given a path and transform will return the column and its index . If not found will return None None .
def get_column(self, item_path, item_doc_type, column_transform):
        """
        Given a path and transform, will return the column and its index. If not found, will
        return None, None.

        :param item_path: A list of path nodes that identify a column
        :param item_doc_type: The doc type of the item (often just ExportItem). If getting
                UserDefinedExportColumn, set this to None
        :param column_transform: A transform that is applied on the column
        :returns index, column: The index of the column in the list and an ExportColumn
        """

        string_item_path = self._create_index(item_path, column_transform)

        # Previously we iterated over self.columns with each call to return the
        # index. Now we do an index lookup on the string-ified path names for
        # self.columns and regenerate it only when the length of self.columns
        # changes. This happens frequently when the table is being constructed.
        if (not hasattr(self, '_string_column_paths')
                or len(self._string_column_paths) != len(self.columns)):
            self._regenerate_column_cache()

        # While unlikely, it is possible for the same path to be used for multiple items.
        # This can occur, for example, when a new reserved case property is introduced.
        # In this case, the reserved property will be an 'ExportItem', while a user-defined
        #  case property would be a 'ScalarItem'.
        # If we can ensure that paths are one-to-one with items, this can be removed in the future.
        indices = [index for (index, path) in enumerate(self._string_column_paths) if path == string_item_path]
        for index in indices:
            column = self.columns[index]

            # The column cache can currently get out of sync because other code directly modifies
            # the columns. For example, ExportInstance._move_selected_columns_to_top just completely
            # overwrites column order without updating our cache.
            # TODO: Modify code such that all table manipulation is done through this class
            if column.item.path != item_path:
                self._regenerate_column_cache()
                index = self._string_column_paths.index(string_item_path)
                column = self.columns[index]

            # Despite the column being found based on a key containing the item_path and transform,
            # both still need to be checked here to prevent the edge case where the the path or the transform
            # contain formatting that makes them blend together.
            if (column.item.path == item_path
                    and column.item.transform == column_transform
                    and column.item.doc_type == item_doc_type):
                return index, column
            elif (isinstance(column, UserDefinedExportColumn)
                    and column.custom_path == item_path
                    and item_doc_type is None):
                return index, column

        return None, None
def get_column ( self , item_path , item_doc_type , column_transform ) : string_item_path = self . _create_index ( item_path , column_transform ) # Previously we iterated over self.columns with each call to return the # index. Now we do an index lookup on the string-ified path names for # self.columns and regenerate it only when the length of self.columns # changes. This happens frequently when the table is being constructed. if ( not hasattr ( self , '_string_column_paths' ) or len ( self . _string_column_paths ) != len ( self . columns ) ) : self . _regenerate_column_cache ( ) # While unlikely, it is possible for the same path to be used for multiple items. # This can occur, for example, when a new reserved case property is introduced. # In this case, the reserved property will be an 'ExportItem', while a user-defined #  case property would be a 'ScalarItem'. # If we can ensure that paths are one-to-one with items, this can be removed in the future. indices = [ index for ( index , path ) in enumerate ( self . _string_column_paths ) if path == string_item_path ] for index in indices : column = self . columns [ index ] # The column cache can currently get out of sync because other code directly modifies # the columns. For example, ExportInstance._move_selected_columns_to_top just completely # overwrites column order without updating our cache. # TODO: Modify code such that all table manipulation is done through this class if column . item . path != item_path : self . _regenerate_column_cache ( ) index = self . _string_column_paths . index ( string_item_path ) column = self . columns [ index ] # Despite the column being found based on a key containing the item_path and transform, # both still need to be checked here to prevent the edge case where the the path or the transform # contain formatting that makes them blend together. if ( column . item . path == item_path and column . item . transform == column_transform and column . item . doc_type == item_doc_type ) : return index , column elif ( isinstance ( column , UserDefinedExportColumn ) and column . custom_path == item_path and item_doc_type is None ) : return index , column return None , None