示例#1
0
    def listSyntax(self):
        """Scan the syntax themes folder and list all themes.
        """
        if self._syntaxList:
            return self._syntaxList

        confParser = NWConfigParser()
        for syntaxKey, syntaxPath in self._availSyntax.items():
            logger.verbose("Checking theme syntax for '%s'", syntaxKey)
            syntaxName = _loadInternalName(confParser, syntaxPath)
            if syntaxName:
                self._syntaxList.append((syntaxKey, syntaxName))

        self._syntaxList = sorted(self._syntaxList, key=lambda x: x[1])

        return self._syntaxList
示例#2
0
    def listThemes(self):
        """Scan the GUI themes folder and list all themes.
        """
        if self._themeList:
            return self._themeList

        confParser = NWConfigParser()
        for themeKey, themePath in self._availThemes.items():
            logger.verbose("Checking theme config for '%s'", themeKey)
            themeName = _loadInternalName(confParser, themePath)
            if themeName:
                self._themeList.append((themeKey, themeName))

        self._themeList = sorted(self._themeList, key=lambda x: x[1])

        return self._themeList
示例#3
0
    def listThemes(self):
        """Scan the icons themes folder and list all themes.
        """
        if self._themeList:
            return self._themeList

        confParser = NWConfigParser()
        for themeDir in os.listdir(self._iconPath):
            themePath = os.path.join(self._iconPath, themeDir)
            if not os.path.isdir(themePath):
                continue

            logger.verbose("Checking icon theme config for '%s'", themeDir)
            themeConf = os.path.join(themePath, self._confName)
            themeName = _loadInternalName(confParser, themeConf)
            if themeName:
                self._themeList.append((themeDir, themeName))

        self._themeList = sorted(self._themeList, key=lambda x: x[1])

        return self._themeList
示例#4
0
    def saveConfig(self):
        """Save the current preferences to file.
        """
        logger.debug("Saving config file")
        if self.confPath is None:
            return False

        theConf = NWConfigParser()

        theConf["Main"] = {
            "timestamp": formatTimeStamp(time()),
            "theme": str(self.guiTheme),
            "syntax": str(self.guiSyntax),
            "icons": str(self.guiIcons),
            "guifont": str(self.guiFont),
            "guifontsize": str(self.guiFontSize),
            "lastnotes": str(self.lastNotes),
            "guilang": str(self.guiLang),
            "hidevscroll": str(self.hideVScroll),
            "hidehscroll": str(self.hideHScroll),
        }

        theConf["Sizes"] = {
            "geometry": self._packList(self.winGeometry),
            "preferences": self._packList(self.prefGeometry),
            "projcols": self._packList(self.projColWidth),
            "mainpane": self._packList(self.mainPanePos),
            "docpane": self._packList(self.docPanePos),
            "viewpane": self._packList(self.viewPanePos),
            "outlinepane": self._packList(self.outlnPanePos),
            "fullscreen": str(self.isFullScreen),
        }

        theConf["Project"] = {
            "autosaveproject": str(self.autoSaveProj),
            "autosavedoc": str(self.autoSaveDoc),
            "emphlabels": str(self.emphLabels),
        }

        theConf["Editor"] = {
            "textfont": str(self.textFont),
            "textsize": str(self.textSize),
            "width": str(self.textWidth),
            "margin": str(self.textMargin),
            "tabwidth": str(self.tabWidth),
            "focuswidth": str(self.focusWidth),
            "hidefocusfooter": str(self.hideFocusFooter),
            "justify": str(self.doJustify),
            "autoselect": str(self.autoSelect),
            "autoreplace": str(self.doReplace),
            "repsquotes": str(self.doReplaceSQuote),
            "repdquotes": str(self.doReplaceDQuote),
            "repdash": str(self.doReplaceDash),
            "repdots": str(self.doReplaceDots),
            "scrollpastend": str(self.scrollPastEnd),
            "autoscroll": str(self.autoScroll),
            "autoscrollpos": str(self.autoScrollPos),
            "fmtsinglequote": self._packList(self.fmtSingleQuotes),
            "fmtdoublequote": self._packList(self.fmtDoubleQuotes),
            "fmtpadbefore": str(self.fmtPadBefore),
            "fmtpadafter": str(self.fmtPadAfter),
            "fmtpadthin": str(self.fmtPadThin),
            "spellcheck": str(self.spellLanguage),
            "showtabsnspaces": str(self.showTabsNSpaces),
            "showlineendings": str(self.showLineEndings),
            "showmultispaces": str(self.showMultiSpaces),
            "wordcounttimer": str(self.wordCountTimer),
            "bigdoclimit": str(self.bigDocLimit),
            "incnoteswcount": str(self.incNotesWCount),
            "showfullpath": str(self.showFullPath),
            "highlightquotes": str(self.highlightQuotes),
            "allowopensquote": str(self.allowOpenSQuote),
            "allowopendquote": str(self.allowOpenDQuote),
            "highlightemph": str(self.highlightEmph),
            "stopwhenidle": str(self.stopWhenIdle),
            "useridletime": str(self.userIdleTime),
        }

        theConf["Backup"] = {
            "backuppath": str(self.backupPath),
            "backuponclose": str(self.backupOnClose),
            "askbeforebackup": str(self.askBeforeBackup),
        }

        theConf["State"] = {
            "showrefpanel": str(self.showRefPanel),
            "viewcomments": str(self.viewComments),
            "viewsynopsis": str(self.viewSynopsis),
            "searchcase": str(self.searchCase),
            "searchword": str(self.searchWord),
            "searchregex": str(self.searchRegEx),
            "searchloop": str(self.searchLoop),
            "searchnextfile": str(self.searchNextFile),
            "searchmatchcap": str(self.searchMatchCap),
        }

        theConf["Path"] = {
            "lastpath": str(self.lastPath),
        }

        # Write config file
        cnfPath = os.path.join(self.confPath, self.confFile)
        try:
            with open(cnfPath, mode="w", encoding="utf-8") as outFile:
                theConf.write(outFile)
            self.confChanged = False
        except Exception as exc:
            logger.error("Could not save config file")
            logException()
            self.hasError = True
            self.errData.append("Could not save config file")
            self.errData.append(formatException(exc))
            return False

        return True
示例#5
0
    def loadConfig(self):
        """Load preferences from file and replace default settings.
        """
        logger.debug("Loading config file")
        if self.confPath is None:
            return False

        theConf = NWConfigParser()
        cnfPath = os.path.join(self.confPath, self.confFile)
        try:
            with open(cnfPath, mode="r", encoding="utf-8") as inFile:
                theConf.read_file(inFile)
        except Exception as exc:
            logger.error("Could not load config file")
            logException()
            self.hasError = True
            self.errData.append("Could not load config file")
            self.errData.append(formatException(exc))
            return False

        # Main
        cnfSec = "Main"
        self.guiTheme = theConf.rdStr(cnfSec, "theme", self.guiTheme)
        self.guiSyntax = theConf.rdStr(cnfSec, "syntax", self.guiSyntax)
        self.guiIcons = theConf.rdStr(cnfSec, "icons", self.guiIcons)
        self.guiFont = theConf.rdStr(cnfSec, "guifont", self.guiFont)
        self.guiFontSize = theConf.rdInt(cnfSec, "guifontsize",
                                         self.guiFontSize)
        self.lastNotes = theConf.rdStr(cnfSec, "lastnotes", self.lastNotes)
        self.guiLang = theConf.rdStr(cnfSec, "guilang", self.guiLang)
        self.hideVScroll = theConf.rdBool(cnfSec, "hidevscroll",
                                          self.hideVScroll)
        self.hideHScroll = theConf.rdBool(cnfSec, "hidehscroll",
                                          self.hideHScroll)

        # Sizes
        cnfSec = "Sizes"
        self.winGeometry = theConf.rdIntList(cnfSec, "geometry",
                                             self.winGeometry)
        self.prefGeometry = theConf.rdIntList(cnfSec, "preferences",
                                              self.prefGeometry)
        self.projColWidth = theConf.rdIntList(cnfSec, "projcols",
                                              self.projColWidth)
        self.mainPanePos = theConf.rdIntList(cnfSec, "mainpane",
                                             self.mainPanePos)
        self.docPanePos = theConf.rdIntList(cnfSec, "docpane", self.docPanePos)
        self.viewPanePos = theConf.rdIntList(cnfSec, "viewpane",
                                             self.viewPanePos)
        self.outlnPanePos = theConf.rdIntList(cnfSec, "outlinepane",
                                              self.outlnPanePos)
        self.isFullScreen = theConf.rdBool(cnfSec, "fullscreen",
                                           self.isFullScreen)

        # Project
        cnfSec = "Project"
        self.autoSaveProj = theConf.rdInt(cnfSec, "autosaveproject",
                                          self.autoSaveProj)
        self.autoSaveDoc = theConf.rdInt(cnfSec, "autosavedoc",
                                         self.autoSaveDoc)
        self.emphLabels = theConf.rdBool(cnfSec, "emphlabels", self.emphLabels)

        # Editor
        cnfSec = "Editor"
        self.textFont = theConf.rdStr(cnfSec, "textfont", self.textFont)
        self.textSize = theConf.rdInt(cnfSec, "textsize", self.textSize)
        self.textWidth = theConf.rdInt(cnfSec, "width", self.textWidth)
        self.textMargin = theConf.rdInt(cnfSec, "margin", self.textMargin)
        self.tabWidth = theConf.rdInt(cnfSec, "tabwidth", self.tabWidth)
        self.focusWidth = theConf.rdInt(cnfSec, "focuswidth", self.focusWidth)
        self.hideFocusFooter = theConf.rdBool(cnfSec, "hidefocusfooter",
                                              self.hideFocusFooter)
        self.doJustify = theConf.rdBool(cnfSec, "justify", self.doJustify)
        self.autoSelect = theConf.rdBool(cnfSec, "autoselect", self.autoSelect)
        self.doReplace = theConf.rdBool(cnfSec, "autoreplace", self.doReplace)
        self.doReplaceSQuote = theConf.rdBool(cnfSec, "repsquotes",
                                              self.doReplaceSQuote)
        self.doReplaceDQuote = theConf.rdBool(cnfSec, "repdquotes",
                                              self.doReplaceDQuote)
        self.doReplaceDash = theConf.rdBool(cnfSec, "repdash",
                                            self.doReplaceDash)
        self.doReplaceDots = theConf.rdBool(cnfSec, "repdots",
                                            self.doReplaceDots)
        self.scrollPastEnd = theConf.rdInt(cnfSec, "scrollpastend",
                                           self.scrollPastEnd)
        self.autoScroll = theConf.rdBool(cnfSec, "autoscroll", self.autoScroll)
        self.autoScrollPos = theConf.rdInt(cnfSec, "autoscrollpos",
                                           self.autoScrollPos)
        self.fmtSingleQuotes = theConf.rdStrList(cnfSec, "fmtsinglequote",
                                                 self.fmtSingleQuotes)
        self.fmtDoubleQuotes = theConf.rdStrList(cnfSec, "fmtdoublequote",
                                                 self.fmtDoubleQuotes)
        self.fmtPadBefore = theConf.rdStr(cnfSec, "fmtpadbefore",
                                          self.fmtPadBefore)
        self.fmtPadAfter = theConf.rdStr(cnfSec, "fmtpadafter",
                                         self.fmtPadAfter)
        self.fmtPadThin = theConf.rdBool(cnfSec, "fmtpadthin", self.fmtPadThin)
        self.spellLanguage = theConf.rdStr(cnfSec, "spellcheck",
                                           self.spellLanguage)
        self.showTabsNSpaces = theConf.rdBool(cnfSec, "showtabsnspaces",
                                              self.showTabsNSpaces)
        self.showLineEndings = theConf.rdBool(cnfSec, "showlineendings",
                                              self.showLineEndings)
        self.showMultiSpaces = theConf.rdBool(cnfSec, "showmultispaces",
                                              self.showMultiSpaces)
        self.wordCountTimer = theConf.rdFlt(cnfSec, "wordcounttimer",
                                            self.wordCountTimer)
        self.bigDocLimit = theConf.rdInt(cnfSec, "bigdoclimit",
                                         self.bigDocLimit)
        self.incNotesWCount = theConf.rdBool(cnfSec, "incnoteswcount",
                                             self.incNotesWCount)
        self.showFullPath = theConf.rdBool(cnfSec, "showfullpath",
                                           self.showFullPath)
        self.highlightQuotes = theConf.rdBool(cnfSec, "highlightquotes",
                                              self.highlightQuotes)
        self.allowOpenSQuote = theConf.rdBool(cnfSec, "allowopensquote",
                                              self.allowOpenSQuote)
        self.allowOpenDQuote = theConf.rdBool(cnfSec, "allowopendquote",
                                              self.allowOpenDQuote)
        self.highlightEmph = theConf.rdBool(cnfSec, "highlightemph",
                                            self.highlightEmph)
        self.stopWhenIdle = theConf.rdBool(cnfSec, "stopwhenidle",
                                           self.stopWhenIdle)
        self.userIdleTime = theConf.rdInt(cnfSec, "useridletime",
                                          self.userIdleTime)

        # Backup
        cnfSec = "Backup"
        self.backupPath = theConf.rdStr(cnfSec, "backuppath", self.backupPath)
        self.backupOnClose = theConf.rdBool(cnfSec, "backuponclose",
                                            self.backupOnClose)
        self.askBeforeBackup = theConf.rdBool(cnfSec, "askbeforebackup",
                                              self.askBeforeBackup)

        # State
        cnfSec = "State"
        self.showRefPanel = theConf.rdBool(cnfSec, "showrefpanel",
                                           self.showRefPanel)
        self.viewComments = theConf.rdBool(cnfSec, "viewcomments",
                                           self.viewComments)
        self.viewSynopsis = theConf.rdBool(cnfSec, "viewsynopsis",
                                           self.viewSynopsis)
        self.searchCase = theConf.rdBool(cnfSec, "searchcase", self.searchCase)
        self.searchWord = theConf.rdBool(cnfSec, "searchword", self.searchWord)
        self.searchRegEx = theConf.rdBool(cnfSec, "searchregex",
                                          self.searchRegEx)
        self.searchLoop = theConf.rdBool(cnfSec, "searchloop", self.searchLoop)
        self.searchNextFile = theConf.rdBool(cnfSec, "searchnextfile",
                                             self.searchNextFile)
        self.searchMatchCap = theConf.rdBool(cnfSec, "searchmatchcap",
                                             self.searchMatchCap)

        # Path
        cnfSec = "Path"
        self.lastPath = theConf.rdStr(cnfSec, "lastpath", self.lastPath)

        # Check Certain Values for None
        self.spellLanguage = self._checkNone(self.spellLanguage)

        # If we're using straight quotes, disable auto-replace
        if self.fmtSingleQuotes == ["'", "'"] and self.doReplaceSQuote:
            logger.info(
                "Using straight single quotes, so disabling auto-replace")
            self.doReplaceSQuote = False

        if self.fmtDoubleQuotes == ['"', '"'] and self.doReplaceDQuote:
            logger.info(
                "Using straight double quotes, so disabling auto-replace")
            self.doReplaceDQuote = False

        # Check deprecated settings
        if self.guiIcons in ("typicons_colour_dark", "typicons_grey_dark"):
            self.guiIcons = "typicons_dark"
        elif self.guiIcons in ("typicons_colour_light", "typicons_grey_light"):
            self.guiIcons = "typicons_light"

        return True
示例#6
0
    def updateTheme(self):
        """Update the theme map. This is more of an init, since many of
        the GUI icons cannot really be replaced without writing specific
        update functions for the classes where they're used.
        """
        self._themeMap = {}
        themePath = self._getThemePath()
        if themePath is None:
            logger.warning("No icons loaded")
            return False

        self._themePath = themePath
        themeConf = os.path.join(themePath, self._confName)
        logger.info("Loading icon theme '%s'", self.mainConf.guiIcons)

        # Config File
        confParser = NWConfigParser()
        try:
            with open(themeConf, mode="r", encoding="utf-8") as inFile:
                confParser.read_file(inFile)
        except Exception:
            logger.error("Could not load icon theme settings from: %s",
                         themeConf)
            logException()
            return False

        # Main
        cnfSec = "Main"
        if confParser.has_section(cnfSec):
            self.themeName = confParser.rdStr(cnfSec, "name", "")
            self.themeDescription = confParser.rdStr(cnfSec, "description", "")
            self.themeAuthor = confParser.rdStr(cnfSec, "author", "N/A")
            self.themeCredit = confParser.rdStr(cnfSec, "credit", "N/A")
            self.themeUrl = confParser.rdStr(cnfSec, "url", "")
            self.themeLicense = confParser.rdStr(cnfSec, "license", "N/A")
            self.themeLicenseUrl = confParser.rdStr(cnfSec, "licenseurl", "")

        # Populate Icon Map
        cnfSec = "Map"
        if confParser.has_section(cnfSec):
            for iconName, iconFile in confParser.items(cnfSec):
                if iconName not in self.ICON_KEYS:
                    logger.error("Unknown icon name '%s' in config file",
                                 iconName)
                else:
                    iconPath = os.path.join(self._themePath, iconFile)
                    if os.path.isfile(iconPath):
                        self._themeMap[iconName] = iconPath
                        logger.verbose("Icon slot '%s' using file '%s'",
                                       iconName, iconFile)
                    else:
                        logger.error("Icon file '%s' not in theme folder",
                                     iconFile)

        # Check that icons have been defined
        logger.debug("Scanning theme icons")
        for iconKey in self.ICON_KEYS:
            if iconKey in ("novelwriter", "proj_nwx"):
                # These are not part of the theme itself
                continue
            if iconKey not in self._themeMap:
                logger.error("No icon file specified for '%s'", iconKey)

        return True
示例#7
0
    def loadSyntax(self):
        """Load the currently specified syntax highlighter theme.
        """
        logger.info("Loading syntax theme '%s'", self.guiSyntax)

        confParser = NWConfigParser()
        try:
            with open(self.syntaxFile, mode="r", encoding="utf-8") as inFile:
                confParser.read_file(inFile)
        except Exception:
            logger.error("Could not load syntax colours from: %s",
                         self.syntaxFile)
            logException()
            return False

        # Main
        cnfSec = "Main"
        if confParser.has_section(cnfSec):
            self.syntaxName = confParser.rdStr(cnfSec, "name", "")
            self.syntaxDescription = confParser.rdStr(cnfSec, "description",
                                                      "")
            self.syntaxAuthor = confParser.rdStr(cnfSec, "author", "")
            self.syntaxCredit = confParser.rdStr(cnfSec, "credit", "")
            self.syntaxUrl = confParser.rdStr(cnfSec, "url", "")
            self.syntaxLicense = confParser.rdStr(cnfSec, "license", "")
            self.syntaxLicenseUrl = confParser.rdStr(cnfSec, "licenseurl", "")

        # Syntax
        cnfSec = "Syntax"
        if confParser.has_section(cnfSec):
            self.colBack = self._loadColour(confParser, cnfSec, "background")
            self.colText = self._loadColour(confParser, cnfSec, "text")
            self.colLink = self._loadColour(confParser, cnfSec, "link")
            self.colHead = self._loadColour(confParser, cnfSec, "headertext")
            self.colHeadH = self._loadColour(confParser, cnfSec, "headertag")
            self.colEmph = self._loadColour(confParser, cnfSec, "emphasis")
            self.colDialN = self._loadColour(confParser, cnfSec,
                                             "straightquotes")
            self.colDialD = self._loadColour(confParser, cnfSec,
                                             "doublequotes")
            self.colDialS = self._loadColour(confParser, cnfSec,
                                             "singlequotes")
            self.colHidden = self._loadColour(confParser, cnfSec, "hidden")
            self.colKey = self._loadColour(confParser, cnfSec, "keyword")
            self.colVal = self._loadColour(confParser, cnfSec, "value")
            self.colSpell = self._loadColour(confParser, cnfSec,
                                             "spellcheckline")
            self.colError = self._loadColour(confParser, cnfSec, "errorline")
            self.colRepTag = self._loadColour(confParser, cnfSec, "replacetag")
            self.colMod = self._loadColour(confParser, cnfSec, "modifier")

        return True
示例#8
0
    def loadTheme(self):
        """Load the currently specified GUI theme.
        """
        logger.info("Loading GUI theme '%s'", self.guiTheme)

        # Config File
        confParser = NWConfigParser()
        try:
            with open(self.themeFile, mode="r", encoding="utf-8") as inFile:
                confParser.read_file(inFile)
        except Exception:
            logger.error("Could not load theme settings from: %s",
                         self.themeFile)
            logException()
            return False

        # Main
        cnfSec = "Main"
        if confParser.has_section(cnfSec):
            self.themeName = confParser.rdStr(cnfSec, "name", "")
            self.themeDescription = confParser.rdStr(cnfSec, "description",
                                                     "N/A")
            self.themeAuthor = confParser.rdStr(cnfSec, "author", "N/A")
            self.themeCredit = confParser.rdStr(cnfSec, "credit", "N/A")
            self.themeUrl = confParser.rdStr(cnfSec, "url", "")
            self.themeLicense = confParser.rdStr(cnfSec, "license", "N/A")
            self.themeLicenseUrl = confParser.rdStr(cnfSec, "licenseurl", "")

        # Palette
        cnfSec = "Palette"
        if confParser.has_section(cnfSec):
            self._setPalette(confParser, cnfSec, "window", QPalette.Window)
            self._setPalette(confParser, cnfSec, "windowtext",
                             QPalette.WindowText)
            self._setPalette(confParser, cnfSec, "base", QPalette.Base)
            self._setPalette(confParser, cnfSec, "alternatebase",
                             QPalette.AlternateBase)
            self._setPalette(confParser, cnfSec, "text", QPalette.Text)
            self._setPalette(confParser, cnfSec, "tooltipbase",
                             QPalette.ToolTipBase)
            self._setPalette(confParser, cnfSec, "tooltiptext",
                             QPalette.ToolTipText)
            self._setPalette(confParser, cnfSec, "button", QPalette.Button)
            self._setPalette(confParser, cnfSec, "buttontext",
                             QPalette.ButtonText)
            self._setPalette(confParser, cnfSec, "brighttext",
                             QPalette.BrightText)
            self._setPalette(confParser, cnfSec, "highlight",
                             QPalette.Highlight)
            self._setPalette(confParser, cnfSec, "highlightedtext",
                             QPalette.HighlightedText)
            self._setPalette(confParser, cnfSec, "link", QPalette.Link)
            self._setPalette(confParser, cnfSec, "linkvisited",
                             QPalette.LinkVisited)

        # GUI
        cnfSec = "GUI"
        if confParser.has_section(cnfSec):
            self.statNone = self._loadColour(confParser, cnfSec, "statusnone")
            self.statUnsaved = self._loadColour(confParser, cnfSec,
                                                "statusunsaved")
            self.statSaved = self._loadColour(confParser, cnfSec,
                                              "statussaved")

        # CSS File
        cssData = readTextFile(self.cssFile)
        if cssData:
            qApp.setStyleSheet(cssData)

        # Apply Styles
        qApp.setPalette(self._guiPalette)

        return True
示例#9
0
def testBaseCommon_NWConfigParser(fncDir):
    """Test the NWConfigParser subclass.
    """
    tstConf = os.path.join(fncDir, "test.cfg")
    writeFile(tstConf, ("[main]\n"
                        "stropt = value\n"
                        "intopt1 = 42\n"
                        "intopt2 = 42.43\n"
                        "boolopt1 = true\n"
                        "boolopt2 = TRUE\n"
                        "boolopt3 = 1\n"
                        "boolopt4 = 0\n"
                        "list1 = a, b, c\n"
                        "list2 = 17, 18, 19\n"
                        "float1 = 4.2\n"))

    cfgParser = NWConfigParser()
    cfgParser.read(tstConf)

    # Readers
    # =======

    # Read String
    assert cfgParser.rdStr("main", "stropt", "stuff") == "value"
    assert cfgParser.rdStr("main", "boolopt1", "stuff") == "true"
    assert cfgParser.rdStr("main", "intopt1", "stuff") == "42"

    assert cfgParser.rdStr("nope", "stropt", "stuff") == "stuff"
    assert cfgParser.rdStr("main", "blabla", "stuff") == "stuff"

    # Read Boolean
    assert cfgParser.rdBool("main", "boolopt1", None) is True
    assert cfgParser.rdBool("main", "boolopt2", None) is True
    assert cfgParser.rdBool("main", "boolopt3", None) is True
    assert cfgParser.rdBool("main", "boolopt4", None) is False
    assert cfgParser.rdBool("main", "intopt1", None) is None

    assert cfgParser.rdBool("nope", "boolopt1", None) is None
    assert cfgParser.rdBool("main", "blabla", None) is None

    # Read Integer
    assert cfgParser.rdInt("main", "intopt1", 13) == 42
    assert cfgParser.rdInt("main", "intopt2", 13) == 13
    assert cfgParser.rdInt("main", "stropt", 13) == 13

    assert cfgParser.rdInt("nope", "intopt1", 13) == 13
    assert cfgParser.rdInt("main", "blabla", 13) == 13

    # Read Float
    assert cfgParser.rdFlt("main", "intopt1", 13.0) == 42.0
    assert cfgParser.rdFlt("main", "float1", 13.0) == 4.2
    assert cfgParser.rdInt("main", "stropt", 13.0) == 13.0

    assert cfgParser.rdInt("nope", "intopt1", 13.0) == 13.0
    assert cfgParser.rdInt("main", "blabla", 13.0) == 13.0

    # Read String List
    assert cfgParser.rdStrList("main", "list1", []) == []
    assert cfgParser.rdStrList("main", "list1", ["x"]) == ["a"]
    assert cfgParser.rdStrList("main", "list1", ["x", "y"]) == ["a", "b"]
    assert cfgParser.rdStrList("main", "list1",
                               ["x", "y", "z"]) == ["a", "b", "c"]
    assert cfgParser.rdStrList("main", "list1",
                               ["x", "y", "z", "w"]) == ["a", "b", "c", "w"]

    assert cfgParser.rdStrList("main", "stropt", ["x"]) == ["value"]
    assert cfgParser.rdStrList("main", "intopt1", ["x"]) == ["42"]

    assert cfgParser.rdStrList("nope", "list1", ["x"]) == ["x"]
    assert cfgParser.rdStrList("main", "blabla", ["x"]) == ["x"]

    # Read Integer List
    assert cfgParser.rdIntList("main", "list2", []) == []
    assert cfgParser.rdIntList("main", "list2", [1]) == [17]
    assert cfgParser.rdIntList("main", "list2", [1, 2]) == [17, 18]
    assert cfgParser.rdIntList("main", "list2", [1, 2, 3]) == [17, 18, 19]
    assert cfgParser.rdIntList("main", "list2",
                               [1, 2, 3, 4]) == [17, 18, 19, 4]

    assert cfgParser.rdIntList("main", "stropt", [1]) == [1]
    assert cfgParser.rdIntList("main", "boolopt1", [1]) == [1]

    assert cfgParser.rdIntList("nope", "list2", [1]) == [1]
    assert cfgParser.rdIntList("main", "blabla", [1]) == [1]

    # Internal
    # ========

    assert cfgParser._parseLine("main", "stropt", None, 999) is None