WIP - ini edit, error check and syntax highlighting.

This commit is contained in:
Jim Miller 2014-12-29 14:01:29 -06:00
parent 4deeaa4cac
commit f1e9081c8c
6 changed files with 457 additions and 221 deletions

View file

@ -0,0 +1,64 @@
#!/usr/bin/env python
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
from __future__ import (unicode_literals, division,
print_function)
__license__ = 'GPL v3'
__copyright__ = '2014, Jim Miller'
__docformat__ = 'restructuredtext en'
import re
try:
from PyQt5.Qt import (Qt, QSyntaxHighlighter, QTextCharFormat, QBrush)
except ImportError as e:
from PyQt4.Qt import (Qt, QSyntaxHighlighter, QTextCharFormat, QBrush)
class BasicIniHighlighter(QSyntaxHighlighter):
'''
QSyntaxHighlighter class for use with QTextEdit for highlighting
ini config files.
I looked high and low to find a high lighter for basic ini config
format, so I'm leaving this in the project even though I'm not
using.
'''
def __init__( self, parent, theme ):
QSyntaxHighlighter.__init__( self, parent )
self.parent = parent
self.highlightingRules = []
# keyword
self.highlightingRules.append( HighlightingRule( r"^[^:=\s][^:=]*[:=]",
Qt.blue,
Qt.SolidPattern ) )
# section
self.highlightingRules.append( HighlightingRule( r"^\[[^\]]+\]",
Qt.darkBlue,
Qt.SolidPattern ) )
# comment
self.highlightingRules.append( HighlightingRule( r"#[^\n]*" ,
Qt.darkYellow,
Qt.SolidPattern ) )
def highlightBlock( self, text ):
for rule in self.highlightingRules:
for match in rule.pattern.finditer(text):
self.setFormat( match.start(), match.end()-match.start(), rule.highlight )
self.setCurrentBlockState( 0 )
class HighlightingRule():
def __init__( self, pattern, color, style ):
if isinstance(pattern,basestring):
self.pattern = re.compile(pattern)
else:
self.pattern=pattern
charfmt = QTextCharFormat()
brush = QBrush(color, style)
charfmt.setForeground(brush)
self.highlight = charfmt

View file

@ -13,8 +13,6 @@ logger = logging.getLogger(__name__)
import traceback, copy, threading
from collections import OrderedDict
from ConfigParser import ParsingError
try:
from PyQt5.Qt import (QDialog, QWidget, QVBoxLayout, QHBoxLayout, QLabel,
QLineEdit, QFont, QWidget, QTextEdit, QComboBox,
@ -75,7 +73,7 @@ no_trans = { 'pini':'personal.ini',
from calibre_plugins.fanfictiondownloader_plugin.prefs import prefs, PREFS_NAMESPACE
from calibre_plugins.fanfictiondownloader_plugin.dialogs \
import (UPDATE, UPDATEALWAYS, collision_order, save_collisions, RejectListDialog,
EditTextDialog, RejectUrlEntry, errors_dialog)
EditTextDialog, IniTextDialog, RejectUrlEntry, errors_dialog)
from calibre_plugins.fanfictiondownloader_plugin.fanficdownloader.adapters \
import getConfigSections
@ -83,7 +81,8 @@ from calibre_plugins.fanfictiondownloader_plugin.fanficdownloader.adapters \
from calibre_plugins.fanfictiondownloader_plugin.common_utils \
import ( KeyboardConfigDialog, PrefsViewerDialog )
from calibre_plugins.fanfictiondownloader_plugin.ffdl_util import (get_ffdl_config)
from calibre_plugins.fanfictiondownloader_plugin.ffdl_util \
import (test_config)
from calibre.gui2.complete2 import EditWithComplete #MultiCompleteLineEdit
@ -566,8 +565,7 @@ class BasicTab(QWidget):
title=_("Reject Reasons"),
label=_("Customize Reject List Reasons"),
tooltip=_("Customize the Reasons presented when Rejecting URLs"),
save_size_name='ffdl:Reject List Reasons',
use_find=True)
save_size_name='ffdl:Reject List Reasons')
d.exec_()
if d.result() == d.Accepted:
prefs['rejectreasons'] = d.get_plain_text()
@ -632,7 +630,7 @@ class PersonalIniTab(QWidget):
# let edit box fill the space.
def show_defaults(self):
EditTextDialog(self,
IniTextDialog(self,
get_resources('plugin-defaults.ini'),
icon=self.windowIcon(),
title=_('Plugin Defaults'),
@ -643,7 +641,7 @@ class PersonalIniTab(QWidget):
save_size_name='ffdl:defaults.ini').exec_()
def add_ini_button(self):
d = EditTextDialog(self,
d = IniTextDialog(self,
self.personalini,
icon=self.windowIcon(),
title=_("Edit personal.ini"),
@ -658,13 +656,7 @@ class PersonalIniTab(QWidget):
if d.result() == d.Accepted:
self.personalini = unicode(d.get_plain_text())
try:
configini = get_ffdl_config("test1.com?sid=555",
personalini=self.personalini)
errors = configini.test_config()
except ParsingError as pe:
errors = pe.errors
errors = test_config(self.personalini)
if errors:
error = not errors_dialog(self.plugin_action.gui,

View file

@ -7,9 +7,6 @@ __license__ = 'GPL v3'
__copyright__ = '2014, Jim Miller'
__docformat__ = 'restructuredtext en'
import logging
logger = logging.getLogger(__name__)
import traceback, re
from functools import partial
@ -28,8 +25,7 @@ try:
QPushButton, QFont, QLabel, QCheckBox, QIcon, QLineEdit,
QComboBox, QProgressDialog, QTimer, QDialogButtonBox,
QPixmap, Qt, QAbstractItemView, QTextEdit, pyqtSignal,
QGroupBox, QFrame, QTextBrowser, QSize, QAction,
QSyntaxHighlighter, QTextCharFormat, QBrush )
QGroupBox, QFrame, QTextBrowser, QSize, QAction)
except ImportError as e:
from PyQt4 import QtGui
from PyQt4 import QtCore
@ -37,8 +33,7 @@ except ImportError as e:
QPushButton, QFont, QLabel, QCheckBox, QIcon, QLineEdit,
QComboBox, QProgressDialog, QTimer, QDialogButtonBox,
QPixmap, Qt, QAbstractItemView, QTextEdit, pyqtSignal,
QGroupBox, QFrame, QTextBrowser, QSize, QAction, QtCore,
QSyntaxHighlighter, QTextCharFormat, QBrush )
QGroupBox, QFrame, QTextBrowser, QSize, QAction)
try:
from calibre.gui2 import QVariant
@ -72,6 +67,12 @@ from calibre_plugins.fanfictiondownloader_plugin.common_utils \
from calibre_plugins.fanfictiondownloader_plugin.fanficdownloader.geturls import get_urls_from_html, get_urls_from_text
from calibre_plugins.fanfictiondownloader_plugin.fanficdownloader.adapters import getNormalStoryURL
from calibre_plugins.fanfictiondownloader_plugin.fanficdownloader.configurable \
import (get_valid_sections, get_valid_entries,
get_valid_keywords, get_valid_entry_keywords)
from inihighlighter import IniHighlighter
SKIP=_('Skip')
ADDNEW=_('Add New Book')
UPDATE=_('Update EPUB if New Chapters')
@ -1120,15 +1121,73 @@ class EditTextDialog(SizePersistedDialog):
def __init__(self, parent, text,
icon=None, title=None, label=None, tooltip=None,
rejectreasons=[],reasonslabel=None,
save_size_name='ffdl:edit text dialog',
):
SizePersistedDialog.__init__(self, parent, save_size_name)
self.l = QVBoxLayout()
self.setLayout(self.l)
self.label = QLabel(label)
if title:
self.setWindowTitle(title)
if icon:
self.setWindowIcon(icon)
self.l.addWidget(self.label)
self.textedit = QTextEdit(self)
self.textedit.setLineWrapMode(QTextEdit.NoWrap)
self.textedit.setText(text)
self.l.addWidget(self.textedit)
if tooltip:
self.label.setToolTip(tooltip)
self.textedit.setToolTip(tooltip)
if rejectreasons or reasonslabel:
self.reason_edit = EditWithComplete(self,sort_func=lambda x:1)
items = ['']+rejectreasons
self.reason_edit.update_items_cache(items)
self.reason_edit.show_initial_value('')
self.reason_edit.set_separator(None)
self.reason_edit.setToolTip(reasonslabel)
if reasonslabel:
horz = QHBoxLayout()
label = QLabel(reasonslabel)
label.setToolTip(reasonslabel)
horz.addWidget(label)
horz.addWidget(self.reason_edit)
self.l.addLayout(horz)
else:
self.l.addWidget(self.reason_edit)
button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
button_box.accepted.connect(self.accept)
button_box.rejected.connect(self.reject)
self.l.addWidget(button_box)
# Cause our dialog size to be restored from prefs or created on first usage
self.resize_dialog()
def get_plain_text(self):
return unicode(self.textedit.toPlainText())
def get_reason_text(self):
return unicode(self.reason_edit.currentText()).strip()
class IniTextDialog(SizePersistedDialog):
def __init__(self, parent, text,
icon=None, title=None, label=None, tooltip=None,
use_find=False,
read_only=False,
save_size_name='ffdl:edit text dialog',
save_size_name='ffdl:ini text dialog',
):
SizePersistedDialog.__init__(self, parent, save_size_name)
self.keys=dict()
#self.resize(600, 500)
self.l = QVBoxLayout()
self.setLayout(self.l)
self.label = QLabel(label)
@ -1140,7 +1199,12 @@ class EditTextDialog(SizePersistedDialog):
self.textedit = QTextEdit(self)
highlighter = IniHighlighter(self.textedit, "Classic")
highlighter = IniHighlighter(self.textedit,
sections=get_valid_sections(),
keywords=get_valid_keywords(),
entries=get_valid_entries(),
entry_keywords=get_valid_entry_keywords(),
)
self.textedit.setLineWrapMode(QTextEdit.NoWrap)
try:
@ -1193,25 +1257,6 @@ class EditTextDialog(SizePersistedDialog):
self.label.setToolTip(tooltip)
self.textedit.setToolTip(tooltip)
if rejectreasons or reasonslabel:
self.reason_edit = EditWithComplete(self,sort_func=lambda x:1)
items = ['']+rejectreasons
self.reason_edit.update_items_cache(items)
self.reason_edit.show_initial_value('')
self.reason_edit.set_separator(None)
self.reason_edit.setToolTip(reasonslabel)
if reasonslabel:
horz = QHBoxLayout()
label = QLabel(reasonslabel)
label.setToolTip(reasonslabel)
horz.addWidget(label)
horz.addWidget(self.reason_edit)
self.l.addLayout(horz)
else:
self.l.addWidget(self.reason_edit)
button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
button_box.accepted.connect(self.accept)
button_box.rejected.connect(self.reject)
@ -1238,9 +1283,6 @@ class EditTextDialog(SizePersistedDialog):
def get_plain_text(self):
return unicode(self.textedit.toPlainText())
def get_reason_text(self):
return unicode(self.reason_edit.currentText()).strip()
def findFocus(self):
# print("findFocus called")
self.findField.setFocus()
@ -1248,7 +1290,7 @@ class EditTextDialog(SizePersistedDialog):
def find(self):
print("find self.lastStart:%s"%self.lastStart)
#print("find self.lastStart:%s"%self.lastStart)
# Grab the parent's text
text = self.textedit.toPlainText()
@ -1328,117 +1370,3 @@ class ViewLog(QDialog):
txt = self.tb.toPlainText()
QApplication.clipboard().setText(txt)
class IniHighlighter(QSyntaxHighlighter):
def __init__( self, parent, theme ):
QSyntaxHighlighter.__init__( self, parent )
self.parent = parent
keyword = QTextCharFormat()
reservedClasses = QTextCharFormat()
assignmentOperator = QTextCharFormat()
delimiter = QTextCharFormat()
specialConstant = QTextCharFormat()
boolean = QTextCharFormat()
number = QTextCharFormat()
comment = QTextCharFormat()
string = QTextCharFormat()
singleQuotedString = QTextCharFormat()
self.highlightingRules = []
# # keyword
# brush = QBrush( Qt.darkBlue, Qt.SolidPattern )
# keyword.setForeground( brush )
# keyword.setFontWeight( QFont.Bold )
# keywords = [ "break", "else", "for", "if", "in",
# "next", "repeat", "return", "switch",
# "try", "while" ]
# for word in keywords:
# pattern = "\\b" + word + "\\b"
# rule = HighlightingRule( pattern, keyword )
# self.highlightingRules.append( rule )
# # reservedClasses
# reservedClasses.setForeground( brush )
# reservedClasses.setFontWeight( QFont.Bold )
# keywords = [ "array", "character", "complex",
# "data.frame", "double", "factor",
# "function", "integer", "list",
# "logical", "matrix", "numeric",
# "vector" ]
# for word in keywords:
# pattern = "\\b" + word + "\\b"
# rule = HighlightingRule( pattern, reservedClasses )
# self.highlightingRules.append( rule )
# # assignmentOperator
# brush = QBrush( Qt.yellow, Qt.SolidPattern )
# pattern = "(<){1,2}-"
# assignmentOperator.setForeground( brush )
# assignmentOperator.setFontWeight( QFont.Bold )
# rule = HighlightingRule( pattern, assignmentOperator )
# self.highlightingRules.append( rule )
# section
pattern = r"^\[[^\]]+\]"
brush = QBrush( Qt.darkBlue, Qt.SolidPattern )
delimiter.setForeground( brush )
delimiter.setFontWeight( QFont.Bold )
rule = HighlightingRule( pattern, delimiter )
self.highlightingRules.append( rule )
# # specialConstant
# brush = QBrush( Qt.green, Qt.SolidPattern )
# specialConstant.setForeground( brush )
# keywords = [ "Inf", "NA", "NaN", "NULL" ]
# for word in keywords:
# pattern = "\\b" + word + "\\b"
# rule = HighlightingRule( pattern, specialConstant )
# self.highlightingRules.append( rule )
# boolean, case insensitive
boolean.setForeground( brush )
pattern = r"\b(true|false)\b"
rule = HighlightingRule( pattern, boolean )
self.highlightingRules.append( rule )
# # number
# pattern = "[-+]?[0-9]*\.?[0-9]+?([eE][-+]?[0-9]+?)?"
# number.setForeground( brush )
# rule = HighlightingRule( pattern, number )
# self.highlightingRules.append( rule )
# comment
brush = QBrush( Qt.darkGray, Qt.SolidPattern )
pattern = "#[^\n]*"
comment.setForeground( brush )
rule = HighlightingRule( pattern, comment )
self.highlightingRules.append( rule )
# string
brush = QBrush( Qt.red, Qt.SolidPattern )
pattern = "\".*?\""
string.setForeground( brush )
rule = HighlightingRule( pattern, string )
self.highlightingRules.append( rule )
# singleQuotedString
pattern = "\'.*?\'"
singleQuotedString.setForeground( brush )
rule = HighlightingRule( pattern, singleQuotedString )
self.highlightingRules.append( rule )
def highlightBlock( self, text ):
for rule in self.highlightingRules:
for match in rule.pattern.finditer(text):
self.setFormat( match.start(), match.end()-match.start(), rule.format )
self.setCurrentBlockState( 0 )
class HighlightingRule():
def __init__( self, pattern, format ):
if isinstance(pattern,basestring):
self.pattern = re.compile(pattern)
else:
self.pattern=pattern
self.format = format

View file

@ -8,10 +8,11 @@ __copyright__ = '2013, Jim Miller'
__docformat__ = 'restructuredtext en'
from StringIO import StringIO
from ConfigParser import ParsingError
from calibre_plugins.fanfictiondownloader_plugin.fanficdownloader import adapters, exceptions
from calibre_plugins.fanfictiondownloader_plugin.fanficdownloader.configurable import Configuration
from calibre_plugins.fanfictiondownloader_plugin.prefs import (prefs)
from calibre_plugins.fanfictiondownloader_plugin.prefs import prefs
def get_ffdl_personalini():
if prefs['includeimages']:
@ -40,4 +41,15 @@ def get_ffdl_config(url,fileform="epub",personalini=None):
def get_ffdl_adapter(url,fileform="epub",personalini=None):
return adapters.getAdapter(get_ffdl_config(url,fileform,personalini),url)
def test_config(initext):
configini = get_ffdl_config("test1.com?sid=555",
personalini=initext)
try:
errors = configini.test_config()
except ParsingError as pe:
errors = pe.errors
return errors

View file

@ -0,0 +1,115 @@
#!/usr/bin/env python
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
from __future__ import (unicode_literals, division,
print_function)
__license__ = 'GPL v3'
__copyright__ = '2014, Jim Miller'
__docformat__ = 'restructuredtext en'
import re
try:
from PyQt5.Qt import (Qt, QSyntaxHighlighter, QTextCharFormat, QBrush, QFont)
except ImportError as e:
from PyQt4.Qt import (Qt, QSyntaxHighlighter, QTextCharFormat, QBrush, QFont)
# r'add_to_+key
class IniHighlighter(QSyntaxHighlighter):
'''
QSyntaxHighlighter class for use with QTextEdit for highlighting
ini config files.
'''
def __init__( self, parent, sections=[], keywords=[], entries=[], entry_keywords=[] ):
QSyntaxHighlighter.__init__( self, parent )
self.parent = parent
self.highlightingRules = []
# *all* keywords -- change known later.
self.errorRule = HighlightingRule( r"^[^:=\s][^:=]*[:=]", Qt.red )
self.highlightingRules.append( self.errorRule )
# *all* entry keywords -- change known later.
reentrykeywords = r'('+(r'|'.join([ e % r'[a-zA-Z0-9_]+' for e in entry_keywords ]))+r')'
self.highlightingRules.append( HighlightingRule( r"^(add_to_)?"+reentrykeywords+r"\s*[:=]", Qt.darkMagenta ) )
# true/false -- just to be nice.
self.highlightingRules.append( HighlightingRule( r"\b(true|false)\b", Qt.darkGreen ) )
if entries:
# *known* entries
reentries = r'('+(r'|'.join(entries))+r')'
self.highlightingRules.append( HighlightingRule( r"\b"+reentries+r"\b", Qt.darkGreen ) )
# *known* entry keywords
reentrykeywords = r'('+(r'|'.join([ e % reentries for e in entry_keywords ]))+r')'
self.highlightingRules.append( HighlightingRule( r"^(add_to_)?"+reentrykeywords+r"\s*[:=]", Qt.blue ) )
# *known* keywords
rekeywords = r'('+(r'|'.join(keywords))+r')'
self.highlightingRules.append( HighlightingRule( r"^(add_to_)?"+rekeywords+r"\s*[:=]", Qt.blue ) )
# *all* sections -- change known later.
self.highlightingRules.append( HighlightingRule( r"^\[[^\]]+\].*?$", Qt.red, QFont.Bold, blocknum=1 ) )
if sections:
# *known* sections
resections = r'('+(r'|'.join(sections))+r')'
resections = resections.replace('.','\.') #escape dots.
self.highlightingRules.append( HighlightingRule( r"^\["+resections+r"\]\s*$", Qt.darkBlue, QFont.Bold, blocknum=2 ) )
# test story sections
self.teststoryRule = HighlightingRule( r"^\[teststory:([0-9]+|defaults)\]", Qt.darkCyan, blocknum=3 )
self.highlightingRules.append( self.teststoryRule )
# NOT comments -- but can be custom columns, so don't flag.
#self.highlightingRules.append( HighlightingRule( r"(?<!^)#[^\n]*" , Qt.red ) )
# comments -- comments must start from column 0.
self.commentRule = HighlightingRule( r"^#[^\n]*" , Qt.darkYellow )
self.highlightingRules.append( self.commentRule )
def highlightBlock( self, text ):
is_comment = False
blocknum = self.previousBlockState()
for rule in self.highlightingRules:
for match in rule.pattern.finditer(text):
self.setFormat( match.start(), match.end()-match.start(), rule.highlight )
if rule == self.commentRule:
is_comment = True
if rule.blocknum > 0:
blocknum = rule.blocknum
if not is_comment:
# unknown section, error all:
if blocknum == 1 and blocknum == self.previousBlockState():
self.setFormat( 0, len(text), self.errorRule.highlight )
# teststory section rules:
if blocknum == 3:
self.setFormat( 0, len(text), self.teststoryRule.highlight )
self.setCurrentBlockState( blocknum )
class HighlightingRule():
def __init__( self, pattern, color,
weight=QFont.Normal,
style=Qt.SolidPattern,
blocknum=0):
if isinstance(pattern,basestring):
self.pattern = re.compile(pattern)
else:
self.pattern=pattern
charfmt = QTextCharFormat()
brush = QBrush(color, style)
charfmt.setForeground(brush)
charfmt.setFontWeight(weight)
self.highlight = charfmt
self.blocknum=blocknum

View file

@ -35,31 +35,30 @@ from ConfigParser import DEFAULTSECT, MissingSectionHeaderError, ParsingError
import adapters
class Configuration(ConfigParser.SafeConfigParser):
def __init__(self, site, fileform):
ConfigParser.SafeConfigParser.__init__(self)
self.linenos=dict() # key by section or section,key -> lineno
self.sectionslist = ['defaults']
if site.startswith("www."):
sitewith = site
sitewithout = site.replace("www.","")
def get_valid_sections():
sites = adapters.getConfigSections()
sitesections = ['defaults','overrides']
for section in sites:
sitesections.append(section)
if section.startswith('www.'):
# add w/o www if has www
sitesections.append(section[4:])
else:
sitewith = "www."+site
sitewithout = site
self.addConfigSection(sitewith)
self.addConfigSection(sitewithout)
if fileform:
self.addConfigSection(fileform)
self.addConfigSection(sitewith+":"+fileform)
self.addConfigSection(sitewithout+":"+fileform)
self.addConfigSection("overrides")
self.listTypeEntries = [
# add w/ www if doesn't www
sitesections.append('www.%s'%section)
allowedsections = []
forms=['html','txt','epub','mobi']
allowedsections.extend(forms)
for section in sitesections:
allowedsections.append(section)
for f in forms:
allowedsections.append('%s:%s'%(section,f))
return allowedsections
def get_valid_list_entries():
return list([
'category',
'genre',
'characters',
@ -70,9 +69,10 @@ class Configuration(ConfigParser.SafeConfigParser):
'authorId',
'authorUrl',
'lastupdate',
]
self.validEntries = self.listTypeEntries + [
])
def get_valid_scalar_entries():
return list([
'series',
'seriesUrl',
'language',
@ -97,7 +97,151 @@ class Configuration(ConfigParser.SafeConfigParser):
'seriesHTML',
'langcode',
'output_css',
]
])
def get_valid_entries():
return get_valid_list_entries() + get_valid_scalar_entries()
def get_valid_keywords():
return list(['add_chapter_numbers',
'add_genre_when_multi_category',
'allow_unsafe_filename',
'always_overwrite',
'anthology_tags',
'anthology_title_pattern',
'background_color',
'bulk_load',
'chapter_end',
'chapter_start',
'chapter_title_add_pattern',
'chapter_title_strip_pattern',
'check_next_chapter',
'collect_series',
'connect_timeout',
'convert_images_to',
'cover_content',
'cover_exclusion_regexp',
'custom_columns_settings',
'dateCreated_format',
'datePublished_format',
'dateUpdated_format',
'default_cover_image',
'do_update_hook',
'exclude_notes',
'extra_logpage_entries',
'extra_subject_tags',
'extra_titlepage_entries',
'extra_valid_entries',
'extratags',
'extracategories',
'extragenres',
'extracharacters',
'extraships',
'extrawarnings',
'fail_on_password',
'file_end',
'file_start',
'fileformat',
'find_chapters',
'fix_fimf_blockquotes',
'force_login',
'generate_cover_settings',
'grayscale_images',
'image_max_size',
'include_images',
'include_logpage',
'include_subject_tags',
'include_titlepage',
'include_tocpage',
'(in|ex)clude_metadata_(pre|post)',
'is_adult',
'join_string_authorHTML',
'keep_style_attr',
'keep_summary_html',
'logpage_end',
'logpage_entries',
'logpage_entry',
'logpage_start',
'logpage_update_end',
'logpage_update_start',
'make_directories',
'make_firstimage_cover',
'make_linkhtml_entries',
'max_fg_sleep',
'max_fg_sleep_at_downloads',
'min_fg_sleep',
'never_make_cover',
'no_image_processing',
'non_breaking_spaces',
'nook_img_fix',
'output_css',
'output_filename',
'output_filename_safepattern',
'password',
'post_process_cmd',
'remove_transparency',
'replace_br_with_p',
'replace_hr',
'replace_metadata',
'slow_down_sleep_time',
'sort_ships',
'strip_chapter_numbers',
'strip_chapter_numeral',
'strip_text_links',
'titlepage_end',
'titlepage_entries',
'titlepage_entry',
'titlepage_no_title_entry',
'titlepage_start',
'titlepage_use_table',
'titlepage_wide_entry',
'tocpage_end',
'tocpage_entry',
'tocpage_start',
'tweak_fg_sleep',
'universe_as_series',
'user_agent',
'username',
'website_encodings',
'wide_titlepage_entries',
'windows_eol',
'wrap_width',
'zip_filename',
'zip_output',
])
# *known* entry keywords -- or rather regexps for them.
def get_valid_entry_keywords():
return list(['%s_label',
'(default_value|include_in|join_string|keep_in_order)_%s',])
class Configuration(ConfigParser.SafeConfigParser):
def __init__(self, site, fileform):
ConfigParser.SafeConfigParser.__init__(self)
self.linenos=dict() # key by section or section,key -> lineno
self.sectionslist = ['defaults']
if site.startswith("www."):
sitewith = site
sitewithout = site.replace("www.","")
else:
sitewith = "www."+site
sitewithout = site
self.addConfigSection(sitewith)
self.addConfigSection(sitewithout)
if fileform:
self.addConfigSection(fileform)
self.addConfigSection(sitewith+":"+fileform)
self.addConfigSection(sitewithout+":"+fileform)
self.addConfigSection("overrides")
self.listTypeEntries = get_valid_list_entries()
self.validEntries = get_valid_entries()
def addConfigSection(self,section):
self.sectionslist.insert(0,section)
@ -169,35 +313,6 @@ class Configuration(ConfigParser.SafeConfigParser):
return self.get_config_list(self.sectionslist, key)
def test_config(self):
errors=[]
sites = adapters.getConfigSections()
sitesections = ['defaults','overrides']
for section in sites:
sitesections.append(section)
if section.startswith('www.'):
# add w/o www if has www
sitesections.append(section[4:])
else:
# add w/ www if doesn't www
sitesections.append('www.%s'%section)
allowedsections = []
forms=['html','txt','epub','mobi']
allowedsections.extend(forms)
for section in sitesections:
allowedsections.append(section)
for f in forms:
allowedsections.append('%s:%s'%(section,f))
for section in self.sections():
if section not in allowedsections and 'teststory:' not in section:
errors.append((self.get_lineno(section),"Bad Section Name: %s"%section))
return errors
def get_lineno(self,section,key=None):
if key:
return self.linenos.get(section+','+key,None)
@ -293,7 +408,17 @@ class Configuration(ConfigParser.SafeConfigParser):
# if any parsing errors occurred, raise an exception
if e:
raise e
def test_config(self):
errors=[]
allowedsections = get_valid_sections()
for section in self.sections():
if section not in allowedsections and 'teststory:' not in section:
errors.append((self.get_lineno(section),"Bad Section Name: %s"%section))
return errors
# extended by adapter, writer and story for ease of calling configuration.
class Configurable(object):