From e3fc0797a3341707855c98830ab3c461d33ba70b Mon Sep 17 00:00:00 2001 From: Patrick Aikens Date: Wed, 3 Jan 2018 16:30:21 -0500 Subject: [PATCH 1/3] Convert to Unix line endings, and fix Contains* methods --- dmAutoCreate.py | 296 ++--- dmClasses.py | 3106 +++++++++++++++++++++++------------------------ dmGlobals.py | 942 +++++++------- dmMod.py | 190 +-- iniReadWrite.py | 90 +- pyevent.py | 168 +-- runProcess.py | 430 +++---- 7 files changed, 2610 insertions(+), 2612 deletions(-) diff --git a/dmAutoCreate.py b/dmAutoCreate.py index 3a582f3..08bbf4d 100644 --- a/dmAutoCreate.py +++ b/dmAutoCreate.py @@ -1,149 +1,149 @@ - -import System.Drawing -import System.Windows.Forms - -from System.Drawing import * -from System.Windows.Forms import * - -class dmAutoCreate(Form): - def __init__(self, books=None): - self.InitializeComponent() - self.Books = books - - def InitializeComponent(self): - self._components = System.ComponentModel.Container() - resources = System.Resources.ResourceManager("dmAutoCreate", System.Reflection.Assembly.GetEntryAssembly()) - self._tscMain = System.Windows.Forms.ToolStripContainer() - self._ttHelp = System.Windows.Forms.ToolTip(self._components) - self._tsMain = System.Windows.Forms.ToolStrip() - self._tsbtnDeleteTemplate = System.Windows.Forms.ToolStripButton() - self._tsbtnAddTemplate = System.Windows.Forms.ToolStripButton() - self._splTreeActiveContent = System.Windows.Forms.SplitContainer() - self._treeView1 = System.Windows.Forms.TreeView() - self._tsddTemplateSelect = System.Windows.Forms.ToolStripDropDownButton() - self._defaultToolStripMenuItem = System.Windows.Forms.ToolStripMenuItem() - self._tscMain.ContentPanel.SuspendLayout() - self._tscMain.TopToolStripPanel.SuspendLayout() - self._tscMain.SuspendLayout() - self._tsMain.SuspendLayout() - self._splTreeActiveContent.BeginInit() - self._splTreeActiveContent.Panel1.SuspendLayout() - self._splTreeActiveContent.SuspendLayout() - self.SuspendLayout() - # - # tscMain - # - # - # tscMain.ContentPanel - # - self._tscMain.ContentPanel.Controls.Add(self._splTreeActiveContent) - self._tscMain.ContentPanel.Size = System.Drawing.Size(858, 526) - self._tscMain.Dock = System.Windows.Forms.DockStyle.Fill - self._tscMain.Location = System.Drawing.Point(0, 0) - self._tscMain.Name = "tscMain" - self._tscMain.Size = System.Drawing.Size(858, 551) - self._tscMain.TabIndex = 0 - self._tscMain.Text = "toolStripContainer1" - # - # tscMain.TopToolStripPanel - # - self._tscMain.TopToolStripPanel.Controls.Add(self._tsMain) - # - # tsMain - # - self._tsMain.Dock = System.Windows.Forms.DockStyle.None - self._tsMain.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden - self._tsMain.Items.AddRange(System.Array[System.Windows.Forms.ToolStripItem]( - [self._tsddTemplateSelect, - self._tsbtnDeleteTemplate, - self._tsbtnAddTemplate])) - self._tsMain.Location = System.Drawing.Point(0, 0) - self._tsMain.Name = "tsMain" - self._tsMain.Size = System.Drawing.Size(858, 25) - self._tsMain.Stretch = True - self._tsMain.TabIndex = 0 - # - # tsbtnDeleteTemplate - # - self._tsbtnDeleteTemplate.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image - self._tsbtnDeleteTemplate.Image = resources.GetObject("tsbtnDeleteTemplate.Image") - self._tsbtnDeleteTemplate.ImageTransparentColor = System.Drawing.Color.Magenta - self._tsbtnDeleteTemplate.Name = "tsbtnDeleteTemplate" - self._tsbtnDeleteTemplate.Size = System.Drawing.Size(23, 22) - self._tsbtnDeleteTemplate.Text = "Delete Template" - # - # tsbtnAddTemplate - # - self._tsbtnAddTemplate.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image - self._tsbtnAddTemplate.Image = resources.GetObject("tsbtnAddTemplate.Image") - self._tsbtnAddTemplate.ImageTransparentColor = System.Drawing.Color.Magenta - self._tsbtnAddTemplate.Name = "tsbtnAddTemplate" - self._tsbtnAddTemplate.Size = System.Drawing.Size(23, 22) - self._tsbtnAddTemplate.Text = "Add New Template" - # - # splTreeActiveContent - # - self._splTreeActiveContent.Dock = System.Windows.Forms.DockStyle.Fill - self._splTreeActiveContent.Location = System.Drawing.Point(0, 0) - self._splTreeActiveContent.Name = "splTreeActiveContent" - # - # splTreeActiveContent.Panel1 - # - self._splTreeActiveContent.Panel1.Controls.Add(self._treeView1) - self._splTreeActiveContent.Size = System.Drawing.Size(858, 526) - self._splTreeActiveContent.SplitterDistance = 216 - self._splTreeActiveContent.TabIndex = 0 - # - # treeView1 - # - self._treeView1.Dock = System.Windows.Forms.DockStyle.Fill - self._treeView1.Location = System.Drawing.Point(0, 0) - self._treeView1.Name = "treeView1" - self._treeView1.Size = System.Drawing.Size(216, 526) - self._treeView1.TabIndex = 0 - # - # tsddTemplateSelect - # - self._tsddTemplateSelect.DropDownItems.AddRange(System.Array[System.Windows.Forms.ToolStripItem]( - [self._defaultToolStripMenuItem])) - self._tsddTemplateSelect.Name = "tsddTemplateSelect" - self._tsddTemplateSelect.Size = System.Drawing.Size(75, 22) - self._tsddTemplateSelect.Text = "Templates" - # - # defaultToolStripMenuItem - # - self._defaultToolStripMenuItem.Name = "defaultToolStripMenuItem" - self._defaultToolStripMenuItem.Size = System.Drawing.Size(152, 22) - self._defaultToolStripMenuItem.Text = "Default" - self._defaultToolStripMenuItem.CheckedChanged += self.TemplateCheckedChanged - # - # dmAutoCreate - # - self.ClientSize = System.Drawing.Size(858, 551) - self.Controls.Add(self._tscMain) - self.Name = "dmAutoCreate" - self.Text = "dmAutoCreate" - self._tscMain.ContentPanel.ResumeLayout(False) - self._tscMain.TopToolStripPanel.ResumeLayout(False) - self._tscMain.TopToolStripPanel.PerformLayout() - self._tscMain.ResumeLayout(False) - self._tscMain.PerformLayout() - self._tsMain.ResumeLayout(False) - self._tsMain.PerformLayout() - self._splTreeActiveContent.Panel1.ResumeLayout(False) - self._splTreeActiveContent.EndInit() - self._splTreeActiveContent.ResumeLayout(False) - self.ResumeLayout(False) - - - def TemplateCheckedChanged(self, sender, e): - RefreshPreview() - pass - - def RefreshPreview(self): - - pass - - def RefreshTemplates(self): - + +import System.Drawing +import System.Windows.Forms + +from System.Drawing import * +from System.Windows.Forms import * + +class dmAutoCreate(Form): + def __init__(self, books=None): + self.InitializeComponent() + self.Books = books + + def InitializeComponent(self): + self._components = System.ComponentModel.Container() + resources = System.Resources.ResourceManager("dmAutoCreate", System.Reflection.Assembly.GetEntryAssembly()) + self._tscMain = System.Windows.Forms.ToolStripContainer() + self._ttHelp = System.Windows.Forms.ToolTip(self._components) + self._tsMain = System.Windows.Forms.ToolStrip() + self._tsbtnDeleteTemplate = System.Windows.Forms.ToolStripButton() + self._tsbtnAddTemplate = System.Windows.Forms.ToolStripButton() + self._splTreeActiveContent = System.Windows.Forms.SplitContainer() + self._treeView1 = System.Windows.Forms.TreeView() + self._tsddTemplateSelect = System.Windows.Forms.ToolStripDropDownButton() + self._defaultToolStripMenuItem = System.Windows.Forms.ToolStripMenuItem() + self._tscMain.ContentPanel.SuspendLayout() + self._tscMain.TopToolStripPanel.SuspendLayout() + self._tscMain.SuspendLayout() + self._tsMain.SuspendLayout() + self._splTreeActiveContent.BeginInit() + self._splTreeActiveContent.Panel1.SuspendLayout() + self._splTreeActiveContent.SuspendLayout() + self.SuspendLayout() + # + # tscMain + # + # + # tscMain.ContentPanel + # + self._tscMain.ContentPanel.Controls.Add(self._splTreeActiveContent) + self._tscMain.ContentPanel.Size = System.Drawing.Size(858, 526) + self._tscMain.Dock = System.Windows.Forms.DockStyle.Fill + self._tscMain.Location = System.Drawing.Point(0, 0) + self._tscMain.Name = "tscMain" + self._tscMain.Size = System.Drawing.Size(858, 551) + self._tscMain.TabIndex = 0 + self._tscMain.Text = "toolStripContainer1" + # + # tscMain.TopToolStripPanel + # + self._tscMain.TopToolStripPanel.Controls.Add(self._tsMain) + # + # tsMain + # + self._tsMain.Dock = System.Windows.Forms.DockStyle.None + self._tsMain.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden + self._tsMain.Items.AddRange(System.Array[System.Windows.Forms.ToolStripItem]( + [self._tsddTemplateSelect, + self._tsbtnDeleteTemplate, + self._tsbtnAddTemplate])) + self._tsMain.Location = System.Drawing.Point(0, 0) + self._tsMain.Name = "tsMain" + self._tsMain.Size = System.Drawing.Size(858, 25) + self._tsMain.Stretch = True + self._tsMain.TabIndex = 0 + # + # tsbtnDeleteTemplate + # + self._tsbtnDeleteTemplate.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image + self._tsbtnDeleteTemplate.Image = resources.GetObject("tsbtnDeleteTemplate.Image") + self._tsbtnDeleteTemplate.ImageTransparentColor = System.Drawing.Color.Magenta + self._tsbtnDeleteTemplate.Name = "tsbtnDeleteTemplate" + self._tsbtnDeleteTemplate.Size = System.Drawing.Size(23, 22) + self._tsbtnDeleteTemplate.Text = "Delete Template" + # + # tsbtnAddTemplate + # + self._tsbtnAddTemplate.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image + self._tsbtnAddTemplate.Image = resources.GetObject("tsbtnAddTemplate.Image") + self._tsbtnAddTemplate.ImageTransparentColor = System.Drawing.Color.Magenta + self._tsbtnAddTemplate.Name = "tsbtnAddTemplate" + self._tsbtnAddTemplate.Size = System.Drawing.Size(23, 22) + self._tsbtnAddTemplate.Text = "Add New Template" + # + # splTreeActiveContent + # + self._splTreeActiveContent.Dock = System.Windows.Forms.DockStyle.Fill + self._splTreeActiveContent.Location = System.Drawing.Point(0, 0) + self._splTreeActiveContent.Name = "splTreeActiveContent" + # + # splTreeActiveContent.Panel1 + # + self._splTreeActiveContent.Panel1.Controls.Add(self._treeView1) + self._splTreeActiveContent.Size = System.Drawing.Size(858, 526) + self._splTreeActiveContent.SplitterDistance = 216 + self._splTreeActiveContent.TabIndex = 0 + # + # treeView1 + # + self._treeView1.Dock = System.Windows.Forms.DockStyle.Fill + self._treeView1.Location = System.Drawing.Point(0, 0) + self._treeView1.Name = "treeView1" + self._treeView1.Size = System.Drawing.Size(216, 526) + self._treeView1.TabIndex = 0 + # + # tsddTemplateSelect + # + self._tsddTemplateSelect.DropDownItems.AddRange(System.Array[System.Windows.Forms.ToolStripItem]( + [self._defaultToolStripMenuItem])) + self._tsddTemplateSelect.Name = "tsddTemplateSelect" + self._tsddTemplateSelect.Size = System.Drawing.Size(75, 22) + self._tsddTemplateSelect.Text = "Templates" + # + # defaultToolStripMenuItem + # + self._defaultToolStripMenuItem.Name = "defaultToolStripMenuItem" + self._defaultToolStripMenuItem.Size = System.Drawing.Size(152, 22) + self._defaultToolStripMenuItem.Text = "Default" + self._defaultToolStripMenuItem.CheckedChanged += self.TemplateCheckedChanged + # + # dmAutoCreate + # + self.ClientSize = System.Drawing.Size(858, 551) + self.Controls.Add(self._tscMain) + self.Name = "dmAutoCreate" + self.Text = "dmAutoCreate" + self._tscMain.ContentPanel.ResumeLayout(False) + self._tscMain.TopToolStripPanel.ResumeLayout(False) + self._tscMain.TopToolStripPanel.PerformLayout() + self._tscMain.ResumeLayout(False) + self._tscMain.PerformLayout() + self._tsMain.ResumeLayout(False) + self._tsMain.PerformLayout() + self._splTreeActiveContent.Panel1.ResumeLayout(False) + self._splTreeActiveContent.EndInit() + self._splTreeActiveContent.ResumeLayout(False) + self.ResumeLayout(False) + + + def TemplateCheckedChanged(self, sender, e): + RefreshPreview() + pass + + def RefreshPreview(self): + + pass + + def RefreshTemplates(self): + pass \ No newline at end of file diff --git a/dmClasses.py b/dmClasses.py index 11d8426..c40597f 100644 --- a/dmClasses.py +++ b/dmClasses.py @@ -1,1554 +1,1552 @@ -import clr -import System -import System.IO -import dmGlobals -from __builtin__ import isinstance -from System import StringSplitOptions -from System import Array - -clr.AddReference('System.Text.RegularExpressions') -clr.AddReference('System.Xml.Linq') - -import System.Text.RegularExpressions -import System.Xml - -from dmGlobals import dmConversionError - -from System.Text.RegularExpressions import Regex, RegexOptions, Match -from System.Collections.Generic import List -from System.Xml.Linq import * -from System.Collections.Generic import Dictionary, List - -from dmGlobals import * -from System.IO import File, Directory - -class dmNode: - """Base of all classes used in a dmCollection""" - - def getName(self): return self.__Name - def setName(self, strName): self.__Name = strName - Name = property(getName, setName) - - def getComment(self): return self.__Comment - def setComment(self, strComment): self.__Comment = strComment - Comment = property(getComment, setComment) - - def getParent(self): return self.__Parent - def setParent(self, dmcContainer): return self.__Parent - Parent = property(getParent, setParent) - - def __init__(self, dmnparent, strParameters): - if dmGlobals.TraceFunctionMessages: - print 'dmNode constructor: dmNode(dmNodeParent, strParameters)' - - self.Parent = dmnparent #this is not necessary for processing dmNodes while running but will come in handy for the editor - self.Name = '' #all inheriting nodes are capable of having a name - self.Comment = '' #all inheriting nodes are capabale of having a comment - - pass - - def ToXML(self, elementName): - if dmGlobals.TraceFunctionMessages: - print 'Method dmNode:ToXML(elementName)' - - baseElement = XElement(XName.Get(elementName)) - - if self.Name != '' and self.Name != None: - baseElement.Add(Xattribute(XName.Get('name'), self.Name)) - - if self.Comment != '' and self.Comment != None: - baseElement.Add(XAttribute(XName.Get('comment'), self.Comment)) - - return baseElement - - def FromXML(self, element): - if dmGlobals.TraceFunctionMessages: - print 'Method dmNode:ToXML(element)' - - if element.Attribute(XName.Get('name')) != None: - self.Name = element.Attribute(XName.Get('name')).Value - - if element.Attribute(XName.Get('comment')) != None: - self.Comment = element.Attribute(('comment')).Value - - pass - - def ProcessBook(self, book, bgWorker): - if dmGlobals.TraceFunctionMessages: - print 'Method: dmNode:ProcessBook(book, backgroundWorker)' - - strReport = '' - - return strReport - -class dmContainer(dmNode): - """a container that contains groups and rulesets [base for dmCollection and dmGroup]""" - - def getGroups(self): return self.__Groups - def setGroups(self, groups): self.__Groups = List[dmGroup](groups) - Groups = property(getGroups, setGroups) - - def getRulesets(self): return self.__Rulesets - def setRulesets(self, rulesets): self.__Rulesets = List[dmRuleset](rulesets) - Rulesets = property(getRulesets, setRulesets) - - def __init__(self, dmnparent, strParameters): - """Initializes a dmContainer object""" - if dmGlobals.TraceFunctionMessages: - print 'dmContainer constructor: dmContainer(dmNodeParent, objParameters)' - - dmNode.__init__(self, dmnparent, strParameters) #initialize all properties inheirited from dmNode - - self.Groups = [] #create Group List - self.Rulesets = [] #create Ruleset List - - pass - - def ParseGroup(self, arrParameters, nStartLine, dmcParent): - if dmGlobals.TraceFunctionMessages: - print 'Method dmConainer:ParseGroup(stingarrayParameters, intStartLine, dmContainerToAddTo)' - - nReturn = nStartLine #integer value that will send back the line number of the final line parsed - newGroup = dmGroup(dmcParent, None) #create a new group that will hold the new group info - - #Parse Group Info from line - if arrParameters[nReturn].startswith(GROUPHEADER): #if the current line starts with the defined GROUP HEADER in dmGlobals - GroupInfo = self.ParseNodeInfo(arrParameters[nReturn]) #Parse info for new Group into a dict Item - - newGroup.Name = GroupInfo['GROUP'].strip() #set Group name from group info - - if GroupInfo.has_key('COMMENT'): #if Comment is provided in GroupInfo - newGroup.Comment = GroupInfo['COMMENT'].strip() #set Comment from GroupInfo - - if GroupInfo.has_key('FILTERSANDDEFAULTS'): #if FILTERSANDDEFAULTS exixts in Group Info - newGroup.FiltersAndDefaults = dmRuleset(None, GroupInfo['FILTERSANDDEFAULTS'].strip()) #set the FiltersAndDefaults Ruleset - - nReturn = nReturn + 1 #increment current line number - - while not arrParameters[nReturn].startswith(dmGlobals.GROUPENDER): #if the line does not equal the "GROUPENDER" defined in dmGlobals - if arrParameters[nReturn].startswith(dmGlobals.GROUPHEADER): #If CURRENT line is a group header - nReturn = self.ParseGroup(arrParameters, nReturn, newGroup) #create and a new Group with this group as parent - elif arrParameters[nReturn].startswith(dmGlobals.RULESETHEADER) or not arrParameters[nReturn].startswith('#'): #else if the current line is a RULESETHEADER or uncommented line - nReturn = self.ParseRuleset(arrParameters, nReturn, newGroup) #Parse and add new Ruleset to this group - else: #otherwise - nReturn = nReturn + 1 #increment line number - - - dmcParent.Groups.Add(newGroup) #finally add the created group to the dmContainer node defined as dmcParent - - nReturn = nReturn + 1 #increment line number - - return nReturn #return next - - def ParseRuleset(self, arrParameters, nStartLine, dmcParent): - """Parses Ruleset as a child Ruleset of the dmContainer: dmcParent""" - if dmGlobals.TraceFunctionMessages: - print 'Method: dmContainer:ParseRuleset(stringarrayParameters, intStartLine, dmContainerToMakeParent)' - - nReturn = nStartLine #assign current defined start line as the line number to return - - newRuleset = dmRuleset(dmcParent, None) #create a new Ruleset to house parsed info - - if arrParameters[nReturn].startswith(dmGlobals.RULESETHEADER): #if the current line is a RulesetHeader - RulesetInfo = self.ParseNodeInfo(arrParameters[nReturn]) #Parse Ruleset Info from line - - if RulesetInfo.has_key('NAME'): #if Ruleset Info Contains a Name key - newRuleset.Name = RulesetInfo['NAME'] #set new Ruleset Name - - if RulesetInfo.has_key('COMMENT'): #if Ruleset Info Contains a Comment Key - newRuleset.Comment = RulesetInfo['COMMENT'] #set new Ruleset Comment - - nReturn = nReturn + 1 #after parsing Ruleset Info move to next line - - newRuleset.ParseParameters(arrParameters[nReturn]) #actually parse ruleset if line is ruleset - - nReturn = nReturn + 1 #set Next Line as the return value - - dmcParent.Rulesets.Add(newRuleset) # add new Ruleset to dmContainer dmcParent - - return nReturn #return next line value - - def ParseNodeInfo(self, strInfo): - """Retrieves info values from headers""" - if dmGlobals.TraceFunctionMessages: print 'Method: dmContainer:ParseNodeInfo(stringInfo)' - NodeInfo = dict() #setup a dictionary to hold values - - parseInfo = strInfo.strip('#') #strip Comment item - parseInfo = parseInfo.lstrip('@ ') - listInfo = parseInfo.split('@ ') #use @ to split Values - - for item in listInfo: - if item != None and item.strip() != '': - dicItem = item.strip().split(' ',1) - if len(dicItem) > 1: - NodeInfo[dicItem[0]] = dicItem[1] - elif len(dicItem) > 0: - NodeInfo[dicItem[0]] = '' - return NodeInfo - - def ParseParameters(self, strParameters): - """does nothing, define this in inherited dmContainers""" - if dmGlobals.TraceFunctionMessages: print 'Method: dmContainer:ParseParameters(objParameters)' - pass - - def ProcessBook(self, book, bgWorker): - if dmGlobals.TraceFunctionMessages: print 'Method: dmContainer:ProcessBook(book, backgroundWorker)' - strReport = '' - - if not bgWorker.CancellationPending: - if dmGlobals.TraceGeneralMessages: print "Processing child groups..." - for group in self.Groups: - if dmGlobals.TraceGeneralMessages: print 'verifying user has not cancelled process...' - if not bgWorker.CancellationPending: - strGroupReport = group.ProcessBook(book, bgWorker) - if strGroupReport != None and strGroupReport != '': - strReport = dmGlobals.AppendReport(strReport, strGroupReport) - else: - strReport = strReport + System.Environment.NewLine + 'Process cancelled by user' - if dmGlobals.TraceGeneralMessages: - print 'Process cancelled by user' - print 'backing out of process...' - break - if dmGlobals.TraceGeneralMessages: print "Processing child rulesets..." - for ruleset in self.Rulesets: - if dmGlobals.TraceGeneralMessages: print 'verifying user has not cancelled process...' - if not bgWorker.CancellationPending: - if dmGlobals.TraceGeneralMessages: print 'Processing book...' - strRulesetReport = ruleset.ProcessBook(book, bgWorker) - if strRulesetReport != None and strRulesetReport != '': - strReport = dmGlobals.AppendReport(strReport, strRulesetReport) - else: - if dmGlobals.TraceGeneralMessages: - print 'Process cancelled by user' - print 'backing out of process...' - break - else: - strReport = dmGlobals.AppendReport(strReport, System.Environment.NewLine + 'Process cancelled by user') - if dmGlobals.TraceGeneralMessages: - print 'Process cancelled by user' - print 'backing out of process...' - if dmGlobals.TraceFunctionMessages: print 'Exiting process dmContainer:ProcessBook(book, bgWorker)' - return strReport - - def ToXML(self, elementName): - if dmGlobals.TraceFunctionMessages: print 'Method: dmContainer:ToXML(stringElementName)' - baseElement = dmNode.ToXML(self, elementName) - for item in self.Groups: - baseElement.append(item.XMLSerialize('group')) - for item in self.Rulesets: - baseElement.append(item.XMLSerialize('ruleset')) - return baseElement - - def FromXML(self, element): - if dmGlobals.TraceFunctionMessages: print 'Method: dmContainer:FromXML(xmlElement)' - dmNode.FromXML(self, element) - - for group in element.Elements(XName.Get('group')): - self.Groups.append(dmGroup(self, group)) - for ruleset in element.Elements(XName.Get('ruleset')): - self.Rulesets.append(dmRuleset(self, ruleset)) - pass - -class dmCollection(dmContainer): - """The base object for groups and rulesets""" - - def getDisabled(self): return self.__Disabled - def setDisabled(self, dmgGroup): self.__Disabled = dmgGroup - Disabled = property(getDisabled, setDisabled) - - def getVersion(self): return self.__Version - def setVersion(self, version): self.__setversion__(version) - Version = property(getVersion, setVersion) - - - def __init__(self, strParameters): - if dmGlobals.TraceFunctionMessages: print 'dmCollection constructor: dmCollection(objParameters)' - if dmGlobals.TraceGeneralMessages: print 'Compiling Ruleset Collection' - dmContainer.__init__(self, None, strParameters) - self.Disabled = dmGroup(self) - self.Version = System.Version(1,1,9,9) - - if strParameters != None: - if isinstance(strParameters, XElement): - self.FromXML(strParameters) - else: - self.ParseParameters(strParameters) - pass - - def __setversion__(self, vItem): - if dmGlobals.TraceFunctionMessages: print 'Method: dmCollection:__setversion__(objVersion)' - if isinstance(vItem, System.Version): - self.Version = vItem - elif isinstance(vItem, str): - self.Version = System.Version.Parse(vItem) - - def ParseParameters(self, strParameters): - """Parses the file to a collection""" - if dmGlobals.TraceFunctionMessages: print 'Method: dmCollection:ParseParameters(objParameters)' - if File.Exists(strParameters): - try: - self.FromXML(System.Xml.Linq.XDocument.Load(strParameters).Root) - except: - self.Parse(File.ReadAllLines(strParameters)) - pass - - def Parse(self, arrParameters): - """Parses the array of strings to a ruleset collection""" - if dmGlobals.TraceFunctionMessages: print 'Method: dmCollection:Parse(stringarrayParameters)' - nReturn = 0 - while nReturn < arrParameters.Length and not arrParameters[nReturn].startswith(dmGlobals.ENDER): - if arrParameters[nReturn].startswith(dmGlobals.AUTHORHEADER): - self.Name = arrParameters[nReturn].replace(dmGlobals.AUTHORHEADER,'') - nReturn = nReturn + 1 - elif arrParameters[nReturn].startswith(dmGlobals.NOTESHEADER): - nReturn = self.RetrieveNotes(arrParameters, nReturn) - elif arrParameters[nReturn].startswith(dmGlobals.RULESETHEADER) or not arrParameters[nReturn].startswith('#'): - nReturn = self.ParseRuleset(arrParameters, nReturn, self) - elif arrParameters[nReturn].startswith(dmGlobals.GROUPHEADER): - nReturn = self.ParseGroup(arrParameters, nReturn, self) - else: nReturn = nReturn + 1 - pass - - def RetrieveNotes(self, arrParameters, nStartLine): - if dmGlobals.TraceFunctionMessages: print 'Method: dmCollection:RetrieveNotes(stringarrayParameters, intStartLine)' - nReturn = nStartLine - self.Comment = '' - while not arrParameters[nReturn].startswith(NOTESENDER): - self.Comment += arrParameters[nReturn].lstrip('# ') + System.Environment.NewLine - nReturn = nReturn + 1 - pass - - def ProcessBook(self, book, bgWorker): - if dmGlobals.TraceFunctionMessages: - print 'Method: dmCollection:ProcessBook(book, backgroundWorker)' - - strReport = '' - - if not bgWorker.CancellationPending: - strReport = dmContainer.ProcessBook(self, book, bgWorker) - - if dmGlobals.TraceFunctionMessages: - print 'Exiting Method: dmCollection:ProcessBook(book, backgroundWorker)' - - return strReport - - def ToXML(self, elementName): - if dmGlobals.TraceFunctionMessages: - print 'Method: dmCollection:ToXML(stringElementName)' - - baseElement = dmContainer.ToXML(self, elementName) - - baseElement.Add(self.Disabled.XMLSerialize('disabled')) - - return baseElement - - def FromXML(self, element): - if dmGlobals.TraceFunctionMessages: print 'Method: dmCollection:FromXML(xmlElement)' - dmContainer.FromXML(self, element) - self.Disabled = dmGroup(self, element.Element(XName.Get('Disabled'))) - self.__setversion__(element.Attribute(XName.Get('version')).Value) - pass - -class dmGroup(dmContainer): - """a named group of groups and rulesets (derived from dmContainer)""" - - def getFiltersAndDefaults(self): return self.__FiltersAndDefaults - def setFiltersAndDefaults(self, dmrRuleset): self.__FiltersAndDefaults = dmrRuleset - FiltersAndDefaults = property(getFiltersAndDefaults, setFiltersAndDefaults) - - def __init__(self, dmcparent, strParameters=None): - if dmGlobals.TraceFunctionMessages: print 'dmGroup constructor: dmGroup(dmContainerParent, objParameters)' - dmContainer.__init__(self, dmcparent, strParameters) - self.FiltersAndDefaults = dmRuleset(self, None) - - if strParameters != None: - if isinstance(strParameters, XElement): - self.FromXML(strParameters) - else: - self.ParseParameters(strParameters) - pass - - def ParseParameters(self, strParameters): - """Parses Parameters of Group from a string or list of parameters""" - if dmGlobals.TraceFunctionMessages: print 'Method: dmGroup:ParseParameters(objParameters)' - if isinstance(strParameters, str) or isinstance(strParameters, list): - arrParameters = list() - if isinstance(strParameters, str): - arrParameters = strParameters.splitlines() #split string into lines - elif isinstance(strParameters, list): - arrParameters = strParameters - - nReturn = 0 - #Parse Group Info from line - if arrParameters[nReturn].startswith(GROUPHEADER): - GroupInfo = self.ParseNodeInfo(arrParameters[nReturn]) - self.Name = GroupInfo['GROUP'].strip() - if GroupInfo.haskey('COMMENT'): - self.Comment = GroupInfo['COMMENT'].strip() - if GroupInfo.haskey('FILTERSANDDEFAULTS'): - self.FiltersAndDefaults = dmRuleset(self,GroupInfo['FILTERSANDDEFAULTS'].strip()) - #increment nReturn - nReturn = nReturn + 1 - - while nReturn < len(arrParameters) and not arrParameters[nReturn].startswith(GROUPENDER): - if arrParameters[nReturn].startswith(GROUPHEADER): - nReturn = self.ParseGroup(arrParameters, nReturn, self) - elif arrParameters[nReturn].startswith(RULESETHEADER) or not arrParameters[nReturn].startswith('#'): - nReturn = ParseRuleset(arrParameters, nReturn, self) - elif isinstance(strParameters, XElement): - self.FromXML(strParameters) - pass - - def MeetsConditions(self, book): - """Determines if the book matches all Rules in FiltersAndDefaults Ruleset""" - if dmGlobals.TraceFunctionMessages: print 'Method: dmGroup:MeetsConditions(book)' - return self.FiltersAndDefaults.MeetsConditions(book) - - def ProcessBook(self, book, bgWorker): - if dmGlobals.TraceFunctionMessages: - print 'Method: dmGroup:ProcessBook(book, backgroundWorker)' - - strReport = '' - - if self.MeetsConditions(book): - if dmGlobals.TraceGeneralMessages: print 'Book: \'' + book.CaptionWithoutTitle + '\' Meets conditions, Processing.' - strReport = dmContainer.ProcessBook(self, book, bgWorker) - - #groupReport - CompiledReport = '' - if dmGlobals.TraceGeneralMessages: print 'Applying Default actions of group \'' + self.Name - - strTempReport = '' - for action in self.FiltersAndDefaults.Actions: - strTempReport = action.Apply(book) + System.Environment.NewLine - if strTempReport != None and strTempReport != '': - CompiledReport = CompiledReport + strTempReport - if CompiledReport != '': - CompiledReport = 'Group: \'' + self.Name + '\' touched book: ' + book.CaptionWithoutTitle + System.Environment.NewLine + CompiledReport - strReport = strReport + System.Environment.NewLine + CompiledReport - else: - if dmGlobals.TraceGeneralMessages: print 'Conditions set forth by filters of group\'' + self.Name + '\' not met, skiping group.' - - if dmGlobals.TraceFunctionMessages: print 'Exiting Method: dmGroup:ProcessBook(book, backgroundWorker)' - - return strReport - - def ToXML(self, elementName): - if dmGlobals.TraceFunctionMessages: print 'Method: dmGroup:ToXML(stringElementName)' - baseElement = dmContainer.ToXML(self, elementName) - baseElement.Add(self.FiltersAndDefaults.ToXML('filtersanddefaults')) - return baseElement - - def FromXML(self, element): - if dmGlobals.TraceFunctionMessages: print 'Method: dmGroup:FromXML(xmlElement)' - dmContainer.FromXML(self, element) - self.FiltersAndDefaults = dmRuleset(self, element.Element(XName.Get('filtersanddefaults'))) - pass - - def ToString(self): - if dmGlobals.TraceFunctionMessages: print 'Method: dmGroup:ToString()' - strReturn = 'Group: ' + self.Name + ' ' + self.FiltersAndDefaults.HumanizeRules() - return strReturn - -class dmRuleset(dmNode): - """Container for rules and actions""" - - def getRulesetMode(self): return self.__RulesetMode - def setRulesetMode(self, strANDorOR): - if strANDorOR.lower() == 'and': self.__RulesetMode = 'AND' - elif strANDorOR.lower() == 'or': self.__RulesetMode = 'OR' - else: self.__RulesetMode = 'AND' - RulesetMode = property(getRulesetMode, setRulesetMode) - - def getRules(self): return self.__Rules - def setRules(self, lstRules): self.__Rules = List[dmRule](lstRules) - Rules = property(getRules, setRules) - - def getActions(self): return self.__Actions - def setActions(self, lstActions): self.__Actions = List[dmAction](lstActions) - Actions = property(getActions, setActions) - - def __init__(self, dmcparent, strParameters=None): - """initializes ruleset instance""" - if dmGlobals.TraceFunctionMessages: print 'dmRuleset constructor: dmRuleset(objParameters)' - dmNode.__init__(self, dmcparent, strParameters) #calls base initialize which adds base fields - self.RulesetMode = 'AND' #sets ruleset mode by default to AND ParseParameters call (from dmNode) later corrrects if and is used - self.Rules = [] #initializes list of rules - self.Actions = [] #initializes list of actions - - if strParameters != None: - if isinstance(strParameters, XElement): - self.FromXML(strParameters) - else: - self.ParseParameters(strParameters) - pass - - def ParseParameters(self, strParameters): - if dmGlobals.TraceFunctionMessages: print 'Method: dmRuleset:ParseParameters(objParameters)' - if isinstance(strParameters, str): - strParsed = strParameters - """parses ruleset""" #note: this function is called from dmNode initialization - if strParsed.startswith('#@ Invalid Ruleset'): - strParsed = strParsed.split('.', 1)[1] - if strParsed.strip() != '': #if we aren't dealing with an empty string - if strParsed.startswith('|'): #if the ruleset mode is set as OR - self.RulesetMode = 'OR' #specify OR as ruleset mode - rulesAndActions = strParsed.lstrip('|').split('=>',1) #split Rules and Actions - self.ParseItemParameters(rulesAndActions[0], 'Rule') #Parse Rules - self.ParseItemParameters(rulesAndActions[1], 'Action') #Parse Actions - elif isinstance(strParameters, XElement): - self.FromXML(strParameters) - pass - - def ParseItemParameters(self, strRules, strRuleOrAction): - """Parses strRules(string) to Rules Or Actions as specified by strRuleOrAction and adds it to this ruleset accordingly""" - if dmGlobals.TraceFunctionMessages: print 'Method: dmRuleset:ParseItemParameters(stringParameters, stringRuleOrAction)' - parameters = strRules.split('> <') #split into individual rules or actions - for parameter in parameters: #for each item in the created list - if parameter.strip() != '': #if the item is not an empty string - if strRuleOrAction == 'Rule': #if indicated as a Rule - self.Rules.Add(dmRule(self, parameter)) #create and add a dmRule instance to this Ruleset's Rules - elif strRuleOrAction == 'Action': #if indicated as an Action - self.Actions.Add(dmAction(self, parameter)) #create and add a dmAction instance to this Ruleset's Actions - pass - - def MeetsConditions(self, book): - if dmGlobals.TraceFunctionMessages: print 'Method: dmRuleset:MeetsConditions(book)' - bReturn = True - if self.Rules.Count < 1: - if dmGlobals.TraceGeneralMessages: print 'There are no rules defined.' - return True - if self.RulesetMode == 'OR': #if we are using OR mode - if dmGlobals.TraceGeneralMessages: print 'Checking rules in OR Mode' - if len(self.Rules) > 0: - bReturn = False #we need False to be default if we are in OR mode but only if there are rules present. - for rule in self.Rules: #iterate over rules - if rule.Match(book): #we only need one match to decide if conditions are met in OR mode - bReturn = True #set return True as soon as a match found - break #and then exit iteration - else: #if we are using AND mode - if dmGlobals.TraceGeneralMessages: print 'Checking rules in AND Mode' - for rule in self.Rules: #iterate through Rules - if not rule.Match(book): # we only need one non-match to determine conditions are not met - bReturn = False #set return to False as soon as non-match found - break #and then exit iteration - return bReturn #return True or False - - def ApplyActions(self, book): - if dmGlobals.TraceFunctionMessages: print 'Method: dmRuleset:ApplyActions(book)' - strReport = '' - for action in self.Actions: - if dmGlobals.TraceGeneralMessages: print 'Applying Actions...' - strTemp = action.Apply(book) - if strTemp != '': - if strReport != '': strReport = strReport + System.Environment.NewLine - if dmGlobals.TraceGeneralMessages: print 'Value was modified, adding info to report' - strReport = strReport + strTemp - if dmGlobals.TraceFunctionMessages: print 'Exiting Method: dmRuleset:ApplyActions(book)' - return strReport - - def ProcessBook(self, book, bgwProcess): - """Begins Processing of Book with this Ruleset""" - if dmGlobals.TraceFunctionMessages: print 'Method: dmRuleset:ProcessBook(book, backgroundWorker)' - strReport = '' - if dmGlobals.TraceGeneralMessages: print 'Checking rules...' - if self.MeetsConditions(book): #if Rules meet conditions - if dmGlobals.TraceGeneralMessages: - print 'Book met all conditional rules' - print 'Processing Ruleset: ' + self.Name - #create a dictionary of values - strTemp = self.ApplyActions(book) - if strTemp != '': - strReport = System.Environment.NewLine + 'Book: ' + book.CaptionWithoutTitle + ' was touched. ' + self.ToString() + System.Environment.NewLine + strTemp - - return strReport - - def ToString(self): - if dmGlobals.TraceFunctionMessages: print 'Method dmRuleset:ToString()' - strReturn = 'Ruleset: ' + self.Name + ' ' + self.HumanizeRules() - return strReturn - - def HumanizeRules(self): - if dmGlobals.TraceFunctionMessages: print 'Method: dmRuleset:HumanizeRules()' - strReturn = '(' - - ruleCount = 0 - while ruleCount < len(self.Rules): - strReturn = strReturn + self.Rules[ruleCount].ToString() - ruleCount = ruleCount + 1 - if ruleCount < len(self.Rules): strReturn = strReturn + ' ' + self.RulesetMode + ' ' - - strReturn = strReturn + ' => ' - - actionCount = 0 - while actionCount < len(self.Actions): - strReturn = strReturn + self.Actions[actionCount].ToString() - actionCount = actionCount + 1 - - strReturn = strReturn + ')' - return strReturn - - def ToXML(self, elementName): - if dmGlobals.TraceFunctionMessages: print 'Method: dmRuleset:ToXML(stringElementName)' - baseElement = dmNode.ToXML(self, elementName) - baseElement.Attribute['rulesetmode'] = self.RulesetMode - for rule in self.Rules: - baseElement.append(rule.XMLSerialize('rule')) - for action in self.Actions: - baseElement.append(action.XMLSerialize('action')) - pass - - def FromXML(self, element): - if dmGlobals.TraceFunctionMessages: print 'Method: dmRuleset:FromXML(xmlElement)' - dmNode.FromXML(self, element) - self.RulesetMode = element.Attribute(XName.Get('rulesetmode')).Value - for rule in element.Elements(XName.Get('rule')): - self.Rules.append(dmRule(self, rule)) - for action in element.Elements(XName.Get('action')): - self.Actions.append(dmAction(self, action)) - pass - -class dmParameters(dmNode): - - def getField(self): - return self._Field - def setField(self, strCompleteField): - self.ParseField(strCompleteField) - Field = property(getField, setField) - - def getModifier(self): - return self._Modifier - def setModifier(self, strModifier): - self._Modifier = strModifier - Modifier = property(getModifier, setModifier) - - def getValue(self): - return self._Value - def setValue(self, strValue): - self._Value = strValue - Value = property(getValue, setValue) - - @property - def IsCustomField(self): - return self.Field in dmGlobals.READONLYKEYS or not self.Field in dmGlobals.ALLOWEDVALS - - @property - def IsValid(self): - if dmGlobals.TraceFunctionMessages: print 'Property: dmParameters:IsValid' - bReturn = True - - #validation for Actions - if isinstance(self, dmAction): - if (not self.Field in dmGlobals.ALLOWEDVALS): - bReturn = False - if not self.Modifier in dmGlobals.ValidValModifiers(self.Field): - bReturn = False - - #validation for Rules - elif isinstance(self, dmRule): - if (not self.Field in dmGlobals.ALLOWEDVALS): - bReturn = False - if not self.Modifier in dmGlobals.ValidValModifiers(self.Field): - bReturn = False - - #TODO: Determine if the value is valid - if not ValueValid(): - bReturn = false - return bReturn - - """base object for dmRule & dmAction instances""" - def __init__(self, dmnparent, strParameters): - """initializes a dmParameter instance""" - dmNode.__init__(self, dmnparent, strParameters) #calls the base dmNode initializer to initialize further fields - self.Field = '' #initializes the field - self.Modifier = '' #initializes the modifier value - self.Value = '' #initializes the value value - - if strParameters != None: - if isinstance(strParameters, XElement): - self.FromXML(strParameters) - else: - self.ParseParameters(strParameters) - pass - - def ValueValid(self): - if dmGlobals.TraceFunctionMessages: print 'Method: dmParameters:ValueValid()' - bReturn = True - if self.Field in dmGlobals.FIELDSNUMERIC: - #check that string can be converted to this type - try: - dmGlobals.StringToFloat(self.Value) - except: - bReturn = False - if self.Field in dmGlobals.FIELDSDATETIME: - #check that string can be converted to this type - try: - dmGlobals.StringToDate(self.Value) - except: - bReturn = False - if self.Field in dmGlobals.FIELDSLANGUAGEISO: - #TODO: ReadLanguages and ISO abbreviations - #check that string can be converted to this type - try: - pass - except: - pass - if self.Field in dmGlobals.FIELDSBOOL: - #check that string can be converted to this type - try: - dmGlobals.StringToBool(self.Value) - except: - bReturn = False - if self.Field in dmGlobals.FIELDSMANGAYESNO: - #check that string can be converted to this type - try: - dmGlobals.StringToMangaYesNo(self.Value) - except: - bReturn = False - if self.Field in dmGlobals.FIELDSYESNO: - #check that string can be converted to this type - try: - dmGlobals.StringToYesNo(self.Value) - except: - bReturn = False - if self.Field in dmGlobals.FIELDSSTRING or self.Field in dmGlobals.FIELD or self.Field in dmGlobals.FIELDSCUSTOM: - if not self.Field in dmGlobals.FIELDSMULTILINE: - #checks for carriage return info in string values that do not support new lines - if '{newline}' in self.Value: - bReturn = False - - return bReturn; - - def ParseParameters(self, strParameters): - """Parses the string containing info for the parameters""" - if dmGlobals.TraceFunctionMessages: print 'Method: dmParameters:ParseParameters(objParameters)' - if isinstance(strParameters, str): - item = strParameters.strip() #strip whitespace from front of string - - item = item.lstrip('<') #remove all instances '<' from front of string - item = item.rstrip('>') #remove all instances '>' from back of string - - tmpParameters = item.split('.',1) #results in [field, modifier&value] - self.ParseField(tmpParameters[0]) #sets complete field from field value in created list - modfierAndValue = tmpParameters[1].split(':',1) #results in [modifier, value] - - self.Modifier = modfierAndValue[0] #set the modifier - if len(modfierAndValue) > 1: #if a value is present - self.Value = modfierAndValue[1] #set the value accordingly - else: - self.Value = '' #otherwise set Value to empty string for safety purposes - - elif isinstance(strParameters, XElement): - self.FromXML(strParameters) - else: - print 'could not parse Parameter Info' + strParameter - pass - - def FieldConvert(self, strValue, strField=None): - if dmGlobals.TraceFunctionMessages: print 'Method: dmParameters:FieldConvert(stringValue, stringFieldName)' - - FieldValue = self.Field - if strField != None: - FieldValue = strField - - theVal = strValue - try: - if FieldValue in dmGlobals.ALLOWEDVALS: - if FieldValue in dmGlobals.FIELDSLIST and not dmGlobals.IsList(strValue): - theVal = strValue.Split(Array[str](dmGlobals.CRLISTDELIMITER), StringSplitOptions.RemoveEmptyEntries) - elif FieldValue in dmGlobals.FIELDSBOOL and not dmGlobals.IsBool(strValue): - theVal = dmGlobals.StringToBool(strValue) - elif FieldValue in dmGlobals.FIELDSDATETIME and not dmGlobals.IsDateTime(strValue): - theVal = dmGlobals.StringToDate(strValue) - elif FieldValue in dmGlobals.FIELDSNUMERIC and not dmGlobals.IsFloat(strValue): - theVal = dmGlobals.StringToFloat(strValue) - elif FieldValue in dmGlobals.FIELDSMANGAYESNO and not dmGlobals.IsMangaYesNo(strValue): - theVal = dmGlobals.StringToMangaYesNo(strValue) - elif FieldValue in dmGlobals.FIELDSYESNO and not dmGlobals.IsYesNo(strValue): - theVal = dmGlobals.StringToYesNo(strValue) - elif FieldValue in dmGlobals.FIELDSPSUEDONUMERIC and not isinstance(strValue,str): - try: - theVal = strValue.ToString() - except: - pass - #otherwise just return the value - except Exception as ex: - - pass - return theVal - - def GetFieldValue(self, book, strFieldName=None): - if dmGlobals.TraceFunctionMessages: print 'Method: dmParameters:GetFieldValue(book, strFieldName)' - objReturn = None - FieldValue = self.Field - if strFieldName != None: - FieldValue = strFieldName - - if dmGlobals.TraceGeneralMessages: print 'Retrieving value for ' + FieldValue + ' field in comic: ' + book.CaptionWithoutTitle #debug Info - - if FieldValue in dmGlobals.FIELDSLIST: - objReturn = self.GetList(book, FieldValue) - elif not FieldValue in dmGlobals.ALLOWEDVALS and not FieldValue in dmGlobals.ALLOWEDKEYS: - objReturn = self.GetCustomField(book, FieldValue) - else: - objReturn = getattr(book, FieldValue) - - - if dmGlobals.TraceGeneralMessages: - print dmGlobals.ToString(objReturn) - print - return objReturn - - def GetList(self, book, strFieldName): - if dmGlobals.TraceFunctionMessages: print 'Method: dmParameters:GetList(book, strFieldName)' - strList = getattr(book, strFieldName) - if strList == None or strList == '': - strList = [] - else: - strList = strList.split(dmGlobals.CRLISTDELIMITER) - return strList - - def GetCustomField(self, book, strFieldName): - print 'Method: dmParameters:GetCustomField(book, strCustomFieldName)' - strTemp = book.GetCustomValue(strFieldName) - if strTemp == None: - strTemp = '' - return strTemp - - def ParseField(self, strCompleteField=''): - """Sets Field & CustomField values properly""" - if dmGlobals.TraceFunctionMessages: print 'Method: dmParameters:ParseField()' - - if strCompleteField.startswith('Custom'): # if CustomField begins with 'Custom' - tmpRegex = Regex("Custom\((.*?)\)") - self._Field = tmpRegex.Match(strCompleteField).Groups[1].Value #set the Field Value - else: #otherwise - self._Field = strCompleteField #Field value == CompleteField value - pass - - def ToXML(self, elementName): - if dmGlobals.TraceFunctionMessages: print 'Method: dmParameters:ToXML(stringElementName)' - baseElement = XElement(elementName) - baseElement.Add(XAttribute(XName.Get('field'), self.Field)) - baseElement.Add((XName.Get('modifier'), self.Modifier)) - baseElement.Add(XAttribute(XName.Get('value'), self.Value)) - return baseElement - - def FromXML(self, element): - if dmGlobals.TraceFunctionMessages: print 'Method: dmParameters:FromXML(xmlElement)' - self.Field = element.Attribute(XName.Get('field')).Value - self.Modifier = element.Attribute(XName.Get('modifier')).Value - self.Value = element.Attribute(XName.Get('value')).Value - - def ReplaceReferenceStrings(self, strValue, book): - """Replaces references to other fields and newline and tab references""" - if dmGlobals.TraceFunctionMessages: print 'dmAction:ReplaceReferenceStrings(self, strValue, book)' - strNewValue = strValue - - strNewValue = strNewValue.replace('{newline}', System.Environment.NewLine) - strNewValue = strNewValue.replace('{tab}', ' ') - - #find field (including custom) references and replace - for x in Regex.Matches(strNewValue, "\\{([^}]+?)}"): - strNewValue = strNewValue.replace(x.Groups[0].Value, self.GetFieldValue(book, x.Groups[1].Value)) - - return strNewValue - - def ToString(self): - if dmGlobals.TraceFunctionMessages: print 'Method: dmParameters:ToString()' - strReturn = self.Field + ' ' + self.Modifier.upper() + ' \'' + self.Value + '\'' - return strReturn - -class dmRule(dmParameters): - """defines a restriction on whether or not defined actions should be applied""" - def __init__(self, dmnparent, strParameters): - """initializes a dmRule instance""" - if dmGlobals.TraceFunctionMessages: print 'dmRule constructor: dmRule(dmNodeParent, objParameters)' - dmParameters.__init__(self, dmnparent, strParameters) #call initialization done in the dmParameters base instance - pass - - def Match(self, book): - """Determines if the rule matches the book file (returns True or False)""" - if dmGlobals.TraceFunctionMessages: print 'Method: dmRule:Match(book)' - return getattr(self, self.Modifier)(book) #sends the book to the designated (by self.Modifier) function to determine if the rule matches - - def Is(self, book): - if dmGlobals.TraceFunctionMessages: print 'Method: dmRule:Is(book)' - - getValue = self.GetFieldValue(book, self.Field) #get Value from book - compareValue = self.FieldConvert(self.ReplaceReferenceStrings(self.Value, book) ,self.Field) #value to compare - - if self.Field in dmGlobals.FIELDSLIST: #deal with list items as individual items - - if len(compareValue) == len(getValue): #only continue if lists are same legnth - count = 0 - for item in compareValue: #iterate through compare list items - for val in getValue: #iterate through book list items - if val.lower() == item.lower(): #compare lowercase list items from book (val) to compare list items (item) - count = count + 1 #if match increment count - if count == len(getValue): #if count ends up equal between book list items and compare list items - return True #set true - else: - if isinstance(getValue, str): - if getValue.lower() == compareValue.lower(): - return True - else: - if getValue == compareValue: #if values match - return True #set true - - return False #if everything else fails set false - - def Not(self, book): - if dmGlobals.TraceFunctionMessages: print 'Method: dmRule:Not(book)' - return not self.Is(book) #return inverse of 'Is(book)' - - def IsAnyOf(self, book): - """Available for string languageISO, psuedonumeric, and numeric""" - if dmGlobals.TraceFunctionMessages: print 'Method: dmRule:IsAnyOf(book)' - - getValue = self.GetFieldValue(book, self.Field) #get Value from book - compareValue = self.ReplaceReferenceStrings(self.Value, book).split(dmGlobals.DMLISTDELIMITER) #value to compare as list - - for word in compareValue: - if isinstance(getValue, str): #if dealing with string - if getValue.lower() == word.lower(): #compare lowercase - return True - if getValue == self.FieldConvert(word, self.Field): - return True - return False - - def NotIsAnyOf(self, book): - if dmGlobals.TraceFunctionMessages: print 'Method: dmRule:NotIsAny(book)' - return not self.IsAnyOf(book) - - def Contains(self, book): - """Only applicable with string and list""" - if dmGlobals.TraceFunctionMessages: print 'Method: dmRule:Contains(book)' - - getValue = self.GetFieldValue(book, self.Field) #get Value from book - compareValue = self.ReplaceReferenceStrings(self.Value, book) #value to compare - - if self.Field in dmGlobals.FIELDSLIST: #search as string list - for check in getValue: - if check.lower().Contains(compareValue.lower()): - return True - else: #search as string - if getValue.lower().Contains(compareValue.lower()): - return True - return False - - def NotContains(self, book): - """Only applicable with string and list""" - if dmGlobals.TraceFunctionMessages: print 'Method: dmRule:NotContains(book)' - return not self.Contains(book) - - def ContainsAnyOf(self, book): - """Only applicable with string and list""" - if dmGlobals.TraceFunctionMessages: print 'Method: dmRule:ContainsAnyOf(book)' - - getValue = self.GetFieldValue(book, self.Field) #get Value from book - compareValue = self.ReplaceReferenceStrings(self.Value, book).split(dmGlobals.DMLISTDELIMITER) #value to compare - - for compareItem in compareValue: - if self.Field in dmGlobals.FIELDSLIST: #compare list against list - for getItem in getValue: #compare list items as lowercase - if getItem.lower().Contains(compareItem.lower()): - return True #return true at first instance of match - else: #compare list against string - if getValue.lower().Contains(compareItem.lower()): #compare string item against list item - return True #return true at first instance of match - return False #all else failing return false - - def NotContainsAnyOf(self, book): - """Only applicable with string and list""" - if dmGlobals.TraceFunctionMessages: print 'Method: dmRule:NotContainsAnyOf(book)' - return not self.ContainsAnyOf(book) - - def ListContains(self, book): - """Only applicable with string and list""" - if dmGlobals.TraceFunctionMessages: print 'Method: dmRule:Contains(book)' - - for check in getValue: - if check.lower() == compareValue.lower(): - return True - - def NotListContains(self, book): - return not self.ListContains(book) - - def ListContainsAnyOf(self, book): - """Only applicable with string and list""" - if dmGlobals.TraceFunctionMessages: print 'Method: dmRule:ContainsAnyOf(book)' - - getValue = self.GetFieldValue(book, self.Field) #get Value from book - compareValue = self.ReplaceReferenceStrings(self.Value, book).split(dmGlobals.DMLISTDELIMITER) #value to compare - - for compareItem in compareValue: - if self.Field in dmGlobals.FIELDSLIST: #compare list against list - for getItem in getValue: #compare list items as lowercase - if getItem.lower().Contains(compareItem.lower()): - return True #return true at first instance of match - else: #compare list against string - if getValue.lower().Contains(compareItem.lower()): #compare string item against list item - return True #return true at first instance of match - - def NotListContainsAnyOf(self, book): - return not self.ListContainsAnyOf(book) - - def ListContainsAllOf(self, book): - - pass - - def ListContainsAllOf(self, book): - return not self.ListContainsAllOf(book) - pass - - - - def ContainsAllOf(self, book): - """Only applicable with string and list""" - if dmGlobals.TraceFunctionMessages: print 'Method: dmRule:ContainsAllOf(book)' - - getValue = self.GetFieldValue(book, self.Field) #get Value from book - compareValue = self.ReplaceReferenceStrings(self.Value, book).split(dmGlobals.DMLISTDELIMITER) #value to compare - - count = 0 - for compareItem in compareValue: - if self.Field in dmGlobals.FIELDSLIST: #compare list against list - for getItem in getValue: #compare list items as lowercase - if getItem.lower().Contains(compareItem.lower()): - count = count + 1 #add a match count on match - else: #compare list against string - if getValue.lower().Contains(compareValue.lower()): #compare string item against list item - count = count + 1 #add a match count on match - return count == len(compareValue) #return wheter count of matches and count of compareValue list equal - - def NotContainsAllOf(self, book): - """Only applicable with string and list""" - if dmGlobals.TraceFunctionMessages: print 'Method: dmRule:NotContainsAllOf(book)' - return not self.ContainsAllOf(book) - - def StartsWith(self, book): - """Only applicable with string""" - if dmGlobals.TraceFunctionMessages: print 'Method: dmRule:StartsWith(book)' - - getValue = self.GetFieldValue(book, self.Field) #get Value from book - compareValue = self.ReplaceReferenceStrings(self.Value, book) #value to compare - - return getValue.lower().startswith(compareValue.lower()) - - def NotStartsWith(self, book): - """Only applicable with string""" - if dmGlobals.TraceFunctionMessages: print 'Method: dmRule:NotStartsWith(book)' - return not self.StartsWith(book) - - def StartsWithAnyOf(self, book): - """Only applicable with string""" - if dmGlobals.TraceFunctionMessages: print 'Method: dmRule:StartsWithAnyOf(book)' - - getValue = self.GetFieldValue(book, self.Field) #get Value from book - compareValue = self.ReplaceReferenceStrings(self.Value, book).split(dmGlobals.DMLISTDELIMITER) #value to compare - - for compareItem in compareValue: #compare each item until truth found - if getValue.lower().startswith(compareItem.lower()): #check if list item at the beginning of string - return True # return true at first instance of match - - return False - - def NotStartsWithAnyOf(self, book): - """Only applicable with string""" - if dmGlobals.TraceFunctionMessages: print 'Method: dmRule:NotNotStartsWithAnyOf(book)' - return not self.StartsWithAnyOf(book) - - def Greater(self, book): - """Only applicable with numeric, psuedo numeric, and date""" - if dmGlobals.TraceFunctionMessages: print 'Method: dmRule:Greater(book)' - - getValue = self.GetFieldValue(book, self.Field) #get Value from book - compareValue = self.FieldConvert(self.Value, self.Field) #value to compare - - if self.Field in dmGlobals.FIELDSNUMERIC: - try: - compareValue = dmGlobals.StringToFloat(compareValue) - return getValue > compareValue - except: - raise Exception('could not convert \'' + self.Value + '\' to Float') - elif self.Field in dmGlobals.FIELDSPSUEDONUMERIC: - count = 0 - prefixGet = '' - prefixCompare = '' - numberCompare = '' - numberGet = '' - suffixGet = '' - suffixCompare = '' - - #seperate prefixes and suffixes - while count < len(getValue) and not getValue[count].isdigit(): - prefixGet = prefixGet + getValue[count] - count = count + 1 - while count < len(getValue) and getValue[count].isdigit(): - numberGet = numberGet + getValue[count] - count = count + 1 - while count < len(getValue): - suffixGet = suffixGet + getValue[count] - count = count + 1 - - count = 0 - - while count < len(compareValue) and not compareValue[count].isdigit(): - prefixCompare = prefixCompare + compareValue[count] - count = count + 1 - while count < len(compareValue) and compareValue[count].isdigit(): - numberCompare = numberCompare + compareValue[count] - count = count + 1 - while count < len(compareValue): - suffixCompare = suffixCompare + compareValue[count] - count = count + 1 - - try: - if prefixCompare == prefixGet: #if prefixes match - if numberGet == numberCompare: - return suffixGet > suffixCompare - else: - return dmGlobals.StringToFloat(numberGet) > dmGlobals.StringToFloat(numberCompare) - else: #return comparison of prefixes - return prefixGet > prefixCompare - - return getValue > compareValue - except: - raise Exception('could not convert \'' + self.Value + '\' to Float') - - elif self.Field in dmGlobals.FIELDSDATETIME: - try: - compareValue = dmGlobals.StringToDate(compareValue) - return getValue > compareValue - except: - raise Exception('could not convert \'' + self.Value + '\' to Date') - - return False - - def GreaterEq(self, book): - """Only applicable with numeric, psuedo numeric, and date""" - if dmGlobals.TraceFunctionMessages: print 'Method: dmRule:GreaterEq(book)' - return self.Greater(book) or self.Is(book) - - def Less(self, book): - """Only applicable with numeric, psuedo numeric, and date""" - if dmGlobals.TraceFunctionMessages: print 'Method: dmRule:Less(book)' - - getValue = self.GetFieldValue(book, self.Field) #get Value from book - compareValue = self.FieldConvert(self.Value, self.Field) #value to compare - - if self.Field in dmGlobals.FIELDSNUMERIC: - try: - compareValue = dmGlobals.StringToFloat(compareValue) - return getValue < compareValue - except: - raise Exception('could not convert \'' + self.Value + '\' to Float') - elif self.Field in dmGlobals.FIELDSPSUEDONUMERIC: - count = 0 - prefixGet = '' - prefixCompare = '' - numberCompare = '' - numberGet = '' - suffixGet = '' - suffixCompare = '' - - #seperate prefixes and suffixes - while count < len(getValue) and not getValue[count].isdigit(): - prefixGet = prefixGet + getValue[count] - count = count + 1 - while count < len(getValue) and getValue[count].isdigit(): - numberGet = numberGet + getValue[count] - count = count + 1 - while count < len(getValue): - suffixGet = suffixGet + getValue[count] - count = count + 1 - - count = 0 - - while count < len(compareValue) and not compareValue[count].isdigit(): - prefixCompare = prefixCompare + compareValue[count] - count = count + 1 - while count < len(compareValue) and compareValue[count].isdigit(): - numberCompare = numberCompare + compareValue[count] - count = count + 1 - while count < len(compareValue): - suffixCompare = suffixCompare + compareValue[count] - count = count + 1 - - try: - if prefixCompare == prefixGet: #if prefixes match - if numberGet == numberCompare: #and number matches - return suffixGet < suffixCompare #return suffix comparison - else: - return dmGlobals.StringToFloat(numberGet) < dmGlobals.StringToFloat(numberCompare) #return Number comparision - else: #return comparison of prefixes - return prefixGet < prefixCompare - except: - raise Exception('could not convert \'' + self.Value + '\' to Float') - - elif self.Field in dmGlobals.FIELDSDATETIME: - try: - compareValue = dmGlobals.StringToDate(compareValue) - return getValue < compareValue - except: - raise Exception('could not convert \'' + self.Value + '\' to Date') - - return False - - def LessEq(self, book): - """Only applicable with numeric, psuedo numeric, and date""" - if dmGlobals.TraceFunctionMessages: print 'Method: dmRule:LessEq(book)' - return self.Less(book) or self.Is(book) - - def Range(self, book): - """Only applicable with numeric, psuedo numeric, and date""" - if dmGlobals.TraceFunctionMessages: print 'Method dmRule:Range(book)' - - getValue = self.GetFieldValue(book, self.Field) - - minVal = self.Value.split(dmGlobals.DMLISTDELIMITER)[0] - maxVal = self.Value.split(dmGlobals.DMLISTDELIMITER)[1] - - if self.Field in dmGlobals.FIELDSNUMERIC or dmGlobals.FIELDSPSUEDONUMERIC: - minVal = dmGlobals.StringToFloat(minVal) - maxVal = dmGlobals.StringToFloat(maxVal) - elif self.Field in dmGlobals.FIELDSDATETIME: - minVal = System.DateTime.Parse(minVal) - maxVal = System.DateTime.Parse(minVal + ' 23:59:59') - if getValue >= minVal and getValue <= maxVal: - return True - return False - - def NotRange(self, book): - """Only applicable with numeric, psuedo numeric, and date""" - if dmGlobals.TraceFunctionMessages: print 'Method: dmRule:NotRange(book)' - return not Range(book) - - def RegEx(self, book): - """Only applicable with string""" - if dmGlobals.TraceFunctionMessages: print 'Method: dmRule:RegEx(book)' - - getValue = self.GetFieldValue(book, self.Field) - compareValue = self.ReplaceReferenceStrings(self.Value, book) - - regExp = Regex(compareValue, RegexOptions.Singleline | RegexOptions.IgnoreCase) - - return regExp.Match(getValue).Success - - def NotRegEx(self, book): - """Only applicable with string""" - if dmGlobals.TraceFunctionMessages: print 'Method: dmRule:NotRegEx(book)' - return not self.RegEx(book) - -class dmAction(dmParameters): - def __init__(self, dmnparent, strParameters): - if dmGlobals.TraceFunctionMessages: print 'dmAction constructor: dmAction(dmRulesetParent, objParameters)' - dmParameters.__init__(self, dmnparent, strParameters) - pass - - def Apply(self, book): - if dmGlobals.TraceFunctionMessages: print 'Method: dmAction:Apply(book)' - strReport = getattr(self, self.Modifier)(book) #send book to function specified by Modifier - return strReport - - def SetFieldValue(self, book, newValue, strField=None): - """Determines the proper write to book technique (Standard or Custom Field) and applies value""" - if dmGlobals.TraceFunctionMessages: print 'Method: dmAction:SetValue(book, objNewValue, stringFieldName)' - - FieldValue = self.Field - - if strField != None: - FieldValue = strField - - previousVal = self.GetFieldValue(book, FieldValue) - - newVal = newValue - - strReport = '' - if FieldValue in dmGlobals.FIELDSLIST: - if dmGlobals.SortLists: - newVal.sort() - newVal = dmGlobals.CRLISTDELIMITER.join(newVal) - previousVal = dmGlobals.CRLISTDELIMITER.join(previousVal) - - if FieldValue in dmGlobals.ALLOWEDVALS: - try: - if FieldValue in dmGlobals.FIELDSNUMERIC: - setattr(book, FieldValue, dmGlobals.StringToFloat(newVal)) #convert to float - else: - setattr(book, FieldValue, newVal.ToString()) - #prepare the report - strReport = ' Field: ' + FieldValue + ' Action: ' + self.ToString() - strReport = strReport + System.Environment.NewLine + ' Previous Value: ' + dmGlobals.ToString(previousVal) - strReport = strReport + System.Environment.NewLine + ' New Value: ' + dmGlobals.ToString(newVal) + '\r\n' - except Exception as er: - #report errors instead - strReport = ' An unexpected error occured in Action: ' + self.ToString() + ' Parent Ruleset : ' + self.Parent.Name - if isinstance(er, dmConversionError): - strReport = strReport + ' Error' + er.msg - pass - else: - self.SetCustomField(book, FieldValue, newVal) - #prepare the report - if strReport != '': strReport = System.Environment.NewLine - strReport = ' CustomField: ' + self.Field + ' Action: ' + self.ToString() - strReport = strReport + System.Environment.NewLine + ' Previous Value: ' + dmGlobals.ToString(previousVal) - strReport = strReport + System.Environment.NewLine + ' New Value: ' + dmGlobals.ToString(newVal) - return strReport - - def SetCustomField(self, book, strCustomFieldName, strNewValue): - """Sets 'CustomField' value of book to strNewValue""" - if dmGlobals.TraceFunctionMessages: print 'SetCustomField(book, stringFieldName, stringNewValue)' - book.SetCustomValue(strCustomFieldName, strNewValue) - pass - - - def GetAppendedField(self, strFieldName, book, strAppendString): - objReturn = self.GetFieldValue(book, strFieldName) - if strFieldName in dmGlobals.FIELDSLIST: - objReturn.append(strAppendString) - elif strFieldName in dmGlobals.FIELDSMULTILINE: - objReturn = objReturn + System.Environment.NewLine + strAppendString - else: - objReturn = objReturn + ' ' + strAppendString - return objReturn - - def SetValue(self, book): - """valid with all action value types""" - if dmGlobals.TraceFunctionMessages: print 'Method: dmAction:SetValue(book)' - if dmGlobals.TraceGeneralMessages: print 'book = ' + book.CaptionWithoutTitle - strReport = '' - - setValue = self.ReplaceReferenceStrings(self.Value, book) #get new Value from local value replacing reference strings - - setValue = self.FieldConvert(setValue, self.Field) #convert setValue to proper object class - - strReport = self.SetFieldValue(book, setValue) - - return strReport - - def Add(self, book): - if dmGlobals.TraceFunctionMessages: print 'Method: dmRule:Add(book)' - - getValue = self.GetFieldValue(book, self.Field) #copy current value - setValue = self.ReplaceReferenceStrings(self.Value,book).split(dmGlobals.DMLISTDELIMITER) #copy value replacing book variables with their values - - strReport = '' - newVal = getValue - - if self.Field in dmGlobals.FIELDSLIST: - addItem = True - for value in setValue: - for existingItem in newVal: - if value.lower() == existingItem.lower(): - addItem = False - break - if addItem: - newVal.Add(value) - else: #since this is only a valid modifier for list and string assume string - for item in setValue: - newVal = newVal + item - - strReport = self.SetFieldValue(book, newVal) #finally set the new value - return strReport - - def Remove(self, book): - if dmGlobals.TraceFunctionMessages: print 'Method: dmAction:Remove(book)' - - getValue = self.GetFieldValue(book, self.Field) #copy current value - setValue = self.ReplaceReferenceStrings(self.Value,book).split(dmGlobals.DMLISTDELIMITER) #copy value replacing book variables with their values - - strReport = '' - newVal = '' - - #set values for list items - if self.Field in dmGlobals.FIELDSLIST: #if the type of field is a list - tmpList = [] #create a list to transfer values to - - for item in getValue: #iterate over the book's list items - addItem = True - for val in setValue: #iterate through the values to remove - if val.lower() == item.lower(): #compare value to remove to book's list item if it does not match - addItem = False - break - if addItem: - tmpList.append(item) #add item to list - - setValue = tmpList - else: #if it's not a list item consider it a string (since only strings and lists have this modifier available) - for val in setValue: #iterate through list of values to remove - newValue = getValue - while val.lower() in newValue.lower(): #as long as string contains the value to remove - idx = newValue.lower().find(val.lower()) #find the index of the value to remove - newValue = newValue.Remove(idx, len(val)) #remove len(val) characters starting from idx - - setValue = newValue - - strReport = self.SetFieldValue(book, setValue) - - - return strReport #return Action Report - - def Replace(self, book): - if dmGlobals.TraceFunctionMessages: print 'Method: dmAction:Replace(book)' - - getValue = self.GetFieldValue(book, self.Field) - setValue = self.ReplaceReferenceStrings(self.Value, book).split(dmGlobals.DMLISTDELIMITER) - newValue = getValue - - - finditem = setValue[0] - replaceitem = setValue[1] - - if self.Field in dmGlobals.FIELDSLIST: - oldList = self.GetFieldValue(book, self.Field) - newList = [] - if not dmGlobals.COMPARE_CASE_SENSITIVE: - for getItem in getValue: - if getItem.lower() == finditem.lower(): - newList.Add(replaceitem) - break - else: - newList.Add(getItem) - else: - for getItem in getValue: - if getItem == finditem: - newList.Add(replaceitem) - break - else: - newList.Add(getItem) - newValue = newList - - else: - idx = 0 - if not dmGlobals.COMPARE_CASE_SENSITIVE: - while finditem.lower() in newValue: - idx = newValue.lower().find(finditem.lower()) #find the index of the value to replace - newValue = newValue.Remove(idx, len(finditem)) - newValue = newValue.Insert(idx, replaceitem) - else: - while finditem.lower() in newValue: - idx = newValue.find(finditem) #find the index of the value to replace - newValue = newValue.Remove(idx, len(finditem)) - newValue = newValue.Insert(idx, replaceitem) - - - strReport = self.SetFieldValue(book, newValue) - - - return strReport - - def Calc(self, book): - """valid for numeric and psuedonumeric""" - if dmGlobals.TraceFunctionMessages: print 'Method: dmAction.Calc(book)' - - setValue = self.ReplaceReferenceStrings(self.Value, book) - - myVal = eval(setValue) - - strReport = self.SetFieldValue(book, myVal) - - return strReport - - def RegexReplace(self, book): - if dmGlobals.TraceFunctionMessages: print 'Method: dmAction:RegexReplace(book)' - - getValue = self.GetFieldValue(book, self.Field) - setValue = self.ReplaceReferenceStrings(self.Value, book).split(dmGlobals.DMLISTDELIMITER, 1) - - strReport = '' - - setPattern = setValue[0] - setFormat = setValue[1] - - RegExp = Regex(setPattern, RegexOptions.IgnoreCase | RegexOptions.Singleline) - - myString = getValue - while RegExp.Match(myString).Success: - myString = RegExp.Replace(myString, setFormat) - - strReport = self.SetFieldValue(book, myString) - - return strReport - - def RegExVarReplace(self, book): - if dmGlobals.TraceFunctionMessages: print 'Method: dmAction:RegexVarReplace(book)' - myString = self.GetFieldValue(book, self.Field) #get the value of the Field in the book - myVal = self.ReplaceReferenceStrings(self.Value, book) #replace reference strings on the proposed value - - strReport = '' #initialize report - - - RegExp = Regex(myVal, RegexOptions.IgnoreCase) #compile the Regex - - matchItem = RegExp.Match(myString) #get the match - if matchItem.Success: - if dmGlobals.TraceGeneralMessages: print 'Book: ' + book.CaptionWithoutTitle + ' field ' + self.Field + ' matched Regex ' + myVal #print Debug Info - if dmGlobals.TraceGeneralMessages: print ' book.' + self.Field + '= ' + dmGlobals.ToString(myString) - if dmGlobals.TraceGeneralMessages: print ' Regex Match = ' + matchItem.Groups[0].Value - - - #iterate over capture names and apply - for groupName in RegExp.GetGroupNames(): - if dmGlobals.TraceGeneralMessages: print 'attempting to apply values to specified fields. WARNING: any unnamed captures will cause an error' - try: - if groupName != '0': #eliminate possible error of group zero being used (group zero is the whole match text) - strFieldName = groupName #get fieldname that's being changed - strNewValue = matchItem.Groups[groupName].Value #get the text that will replace the field - - strReport = strReport + self.SetFieldValue(book, strNewValue, strFieldName) #replace the field - except Exception as er: - - pass - return strReport - - def RegExVarAppend(self, book): - if dmGlobals.TraceFunctionMessages: print 'Method: dmAction:RegexVarAppend(book)' - - - myString = self.GetFieldValue(book, self.Field) #get the value of the Field in the book - myVal = self.ReplaceReferenceStrings(self.Value, book) #replace reference strings on the proposed value - - strReport = '' #initialize report - - - RegExp = Regex(myVal, RegexOptions.IgnoreCase) #compile the Regex - - matchItem = RegExp.Match(myString) #get the match - if matchItem.Success: - if dmGlobals.TraceGeneralMessages: print 'Book: ' + book.CaptionWithoutTitle + ' field ' + self.Field + ' matched Regex ' + myVal #print Debug Info - if dmGlobals.TraceGeneralMessages: print ' book.' + self.Field + '= ' + dmGlobals.ToString(myString) - if dmGlobals.TraceGeneralMessages: print ' Regex Match = ' + matchItem.Groups[0].Value - - - #iterate over capture names and apply - for groupName in RegExp.GetGroupNames(): - if dmGlobals.TraceGeneralMessages: print 'attempting to apply values to specified fields. WARNING: any unnamed captures will cause an error' - try: - if groupName != '0': #eliminate possible error of group zero being used (group zero is the whole match text) - strFieldName = groupName #get fieldname that's being changed - strNewValue = '' - - strNewValue = self.GetAppendedField(strFieldName, book, matchItem.Groups[groupName].Value) #get the text that will replace the field - strOldValue = self.GetFieldValue - strReport = strReport + self.SetFieldValue(book, strNewValue, strFieldName) #replace the field - - except Exception as er: - - pass - return strReport - - - def RemoveLeading(self, book): - if dmGlobals.TraceFunctionMessages: print 'Method: dmAction:RemoveLeading(book)' - - myString = self.GetFieldValue(book) - myVal = self.ReplaceReferenceStrings(self.Value, book) - - if myString.lower().startswith(myVal.lower()): - myString = myString.Remove(0, len(myVal)) - - strReport = self.SetFieldValue(book, myString) - - return strReport \ No newline at end of file +import clr +import System +import System.IO +import dmGlobals +from __builtin__ import isinstance +from System import StringSplitOptions +from System import Array + +clr.AddReference('System.Text.RegularExpressions') +clr.AddReference('System.Xml.Linq') + +import System.Text.RegularExpressions +import System.Xml + +from dmGlobals import dmConversionError + +from System.Text.RegularExpressions import Regex, RegexOptions, Match +from System.Collections.Generic import List +from System.Xml.Linq import * +from System.Collections.Generic import Dictionary, List + +from dmGlobals import * +from System.IO import File, Directory + +class dmNode: + """Base of all classes used in a dmCollection""" + + def getName(self): return self.__Name + def setName(self, strName): self.__Name = strName + Name = property(getName, setName) + + def getComment(self): return self.__Comment + def setComment(self, strComment): self.__Comment = strComment + Comment = property(getComment, setComment) + + def getParent(self): return self.__Parent + def setParent(self, dmcContainer): return self.__Parent + Parent = property(getParent, setParent) + + def __init__(self, dmnparent, strParameters): + if dmGlobals.TraceFunctionMessages: + print 'dmNode constructor: dmNode(dmNodeParent, strParameters)' + + self.Parent = dmnparent #this is not necessary for processing dmNodes while running but will come in handy for the editor + self.Name = '' #all inheriting nodes are capable of having a name + self.Comment = '' #all inheriting nodes are capabale of having a comment + + pass + + def ToXML(self, elementName): + if dmGlobals.TraceFunctionMessages: + print 'Method dmNode:ToXML(elementName)' + + baseElement = XElement(XName.Get(elementName)) + + if self.Name != '' and self.Name != None: + baseElement.Add(Xattribute(XName.Get('name'), self.Name)) + + if self.Comment != '' and self.Comment != None: + baseElement.Add(XAttribute(XName.Get('comment'), self.Comment)) + + return baseElement + + def FromXML(self, element): + if dmGlobals.TraceFunctionMessages: + print 'Method dmNode:ToXML(element)' + + if element.Attribute(XName.Get('name')) != None: + self.Name = element.Attribute(XName.Get('name')).Value + + if element.Attribute(XName.Get('comment')) != None: + self.Comment = element.Attribute(('comment')).Value + + pass + + def ProcessBook(self, book, bgWorker): + if dmGlobals.TraceFunctionMessages: + print 'Method: dmNode:ProcessBook(book, backgroundWorker)' + + strReport = '' + + return strReport + +class dmContainer(dmNode): + """a container that contains groups and rulesets [base for dmCollection and dmGroup]""" + + def getGroups(self): return self.__Groups + def setGroups(self, groups): self.__Groups = List[dmGroup](groups) + Groups = property(getGroups, setGroups) + + def getRulesets(self): return self.__Rulesets + def setRulesets(self, rulesets): self.__Rulesets = List[dmRuleset](rulesets) + Rulesets = property(getRulesets, setRulesets) + + def __init__(self, dmnparent, strParameters): + """Initializes a dmContainer object""" + if dmGlobals.TraceFunctionMessages: + print 'dmContainer constructor: dmContainer(dmNodeParent, objParameters)' + + dmNode.__init__(self, dmnparent, strParameters) #initialize all properties inheirited from dmNode + + self.Groups = [] #create Group List + self.Rulesets = [] #create Ruleset List + + pass + + def ParseGroup(self, arrParameters, nStartLine, dmcParent): + if dmGlobals.TraceFunctionMessages: + print 'Method dmConainer:ParseGroup(stingarrayParameters, intStartLine, dmContainerToAddTo)' + + nReturn = nStartLine #integer value that will send back the line number of the final line parsed + newGroup = dmGroup(dmcParent, None) #create a new group that will hold the new group info + + #Parse Group Info from line + if arrParameters[nReturn].startswith(GROUPHEADER): #if the current line starts with the defined GROUP HEADER in dmGlobals + GroupInfo = self.ParseNodeInfo(arrParameters[nReturn]) #Parse info for new Group into a dict Item + + newGroup.Name = GroupInfo['GROUP'].strip() #set Group name from group info + + if GroupInfo.has_key('COMMENT'): #if Comment is provided in GroupInfo + newGroup.Comment = GroupInfo['COMMENT'].strip() #set Comment from GroupInfo + + if GroupInfo.has_key('FILTERSANDDEFAULTS'): #if FILTERSANDDEFAULTS exixts in Group Info + newGroup.FiltersAndDefaults = dmRuleset(None, GroupInfo['FILTERSANDDEFAULTS'].strip()) #set the FiltersAndDefaults Ruleset + + nReturn = nReturn + 1 #increment current line number + + while not arrParameters[nReturn].startswith(dmGlobals.GROUPENDER): #if the line does not equal the "GROUPENDER" defined in dmGlobals + if arrParameters[nReturn].startswith(dmGlobals.GROUPHEADER): #If CURRENT line is a group header + nReturn = self.ParseGroup(arrParameters, nReturn, newGroup) #create and a new Group with this group as parent + elif arrParameters[nReturn].startswith(dmGlobals.RULESETHEADER) or not arrParameters[nReturn].startswith('#'): #else if the current line is a RULESETHEADER or uncommented line + nReturn = self.ParseRuleset(arrParameters, nReturn, newGroup) #Parse and add new Ruleset to this group + else: #otherwise + nReturn = nReturn + 1 #increment line number + + + dmcParent.Groups.Add(newGroup) #finally add the created group to the dmContainer node defined as dmcParent + + nReturn = nReturn + 1 #increment line number + + return nReturn #return next + + def ParseRuleset(self, arrParameters, nStartLine, dmcParent): + """Parses Ruleset as a child Ruleset of the dmContainer: dmcParent""" + if dmGlobals.TraceFunctionMessages: + print 'Method: dmContainer:ParseRuleset(stringarrayParameters, intStartLine, dmContainerToMakeParent)' + + nReturn = nStartLine #assign current defined start line as the line number to return + + newRuleset = dmRuleset(dmcParent, None) #create a new Ruleset to house parsed info + + if arrParameters[nReturn].startswith(dmGlobals.RULESETHEADER): #if the current line is a RulesetHeader + RulesetInfo = self.ParseNodeInfo(arrParameters[nReturn]) #Parse Ruleset Info from line + + if RulesetInfo.has_key('NAME'): #if Ruleset Info Contains a Name key + newRuleset.Name = RulesetInfo['NAME'] #set new Ruleset Name + + if RulesetInfo.has_key('COMMENT'): #if Ruleset Info Contains a Comment Key + newRuleset.Comment = RulesetInfo['COMMENT'] #set new Ruleset Comment + + nReturn = nReturn + 1 #after parsing Ruleset Info move to next line + + newRuleset.ParseParameters(arrParameters[nReturn]) #actually parse ruleset if line is ruleset + + nReturn = nReturn + 1 #set Next Line as the return value + + dmcParent.Rulesets.Add(newRuleset) # add new Ruleset to dmContainer dmcParent + + return nReturn #return next line value + + def ParseNodeInfo(self, strInfo): + """Retrieves info values from headers""" + if dmGlobals.TraceFunctionMessages: print 'Method: dmContainer:ParseNodeInfo(stringInfo)' + NodeInfo = dict() #setup a dictionary to hold values + + parseInfo = strInfo.strip('#') #strip Comment item + parseInfo = parseInfo.lstrip('@ ') + listInfo = parseInfo.split('@ ') #use @ to split Values + + for item in listInfo: + if item != None and item.strip() != '': + dicItem = item.strip().split(' ',1) + if len(dicItem) > 1: + NodeInfo[dicItem[0]] = dicItem[1] + elif len(dicItem) > 0: + NodeInfo[dicItem[0]] = '' + return NodeInfo + + def ParseParameters(self, strParameters): + """does nothing, define this in inherited dmContainers""" + if dmGlobals.TraceFunctionMessages: print 'Method: dmContainer:ParseParameters(objParameters)' + pass + + def ProcessBook(self, book, bgWorker): + if dmGlobals.TraceFunctionMessages: print 'Method: dmContainer:ProcessBook(book, backgroundWorker)' + strReport = '' + + if not bgWorker.CancellationPending: + if dmGlobals.TraceGeneralMessages: print "Processing child groups..." + for group in self.Groups: + if dmGlobals.TraceGeneralMessages: print 'verifying user has not cancelled process...' + if not bgWorker.CancellationPending: + strGroupReport = group.ProcessBook(book, bgWorker) + if strGroupReport != None and strGroupReport != '': + strReport = dmGlobals.AppendReport(strReport, strGroupReport) + else: + strReport = strReport + System.Environment.NewLine + 'Process cancelled by user' + if dmGlobals.TraceGeneralMessages: + print 'Process cancelled by user' + print 'backing out of process...' + break + if dmGlobals.TraceGeneralMessages: print "Processing child rulesets..." + for ruleset in self.Rulesets: + if dmGlobals.TraceGeneralMessages: print 'verifying user has not cancelled process...' + if not bgWorker.CancellationPending: + if dmGlobals.TraceGeneralMessages: print 'Processing book...' + strRulesetReport = ruleset.ProcessBook(book, bgWorker) + if strRulesetReport != None and strRulesetReport != '': + strReport = dmGlobals.AppendReport(strReport, strRulesetReport) + else: + if dmGlobals.TraceGeneralMessages: + print 'Process cancelled by user' + print 'backing out of process...' + break + else: + strReport = dmGlobals.AppendReport(strReport, System.Environment.NewLine + 'Process cancelled by user') + if dmGlobals.TraceGeneralMessages: + print 'Process cancelled by user' + print 'backing out of process...' + if dmGlobals.TraceFunctionMessages: print 'Exiting process dmContainer:ProcessBook(book, bgWorker)' + return strReport + + def ToXML(self, elementName): + if dmGlobals.TraceFunctionMessages: print 'Method: dmContainer:ToXML(stringElementName)' + baseElement = dmNode.ToXML(self, elementName) + for item in self.Groups: + baseElement.append(item.XMLSerialize('group')) + for item in self.Rulesets: + baseElement.append(item.XMLSerialize('ruleset')) + return baseElement + + def FromXML(self, element): + if dmGlobals.TraceFunctionMessages: print 'Method: dmContainer:FromXML(xmlElement)' + dmNode.FromXML(self, element) + + for group in element.Elements(XName.Get('group')): + self.Groups.append(dmGroup(self, group)) + for ruleset in element.Elements(XName.Get('ruleset')): + self.Rulesets.append(dmRuleset(self, ruleset)) + pass + +class dmCollection(dmContainer): + """The base object for groups and rulesets""" + + def getDisabled(self): return self.__Disabled + def setDisabled(self, dmgGroup): self.__Disabled = dmgGroup + Disabled = property(getDisabled, setDisabled) + + def getVersion(self): return self.__Version + def setVersion(self, version): self.__setversion__(version) + Version = property(getVersion, setVersion) + + + def __init__(self, strParameters): + if dmGlobals.TraceFunctionMessages: print 'dmCollection constructor: dmCollection(objParameters)' + if dmGlobals.TraceGeneralMessages: print 'Compiling Ruleset Collection' + dmContainer.__init__(self, None, strParameters) + self.Disabled = dmGroup(self) + self.Version = System.Version(1,1,9,9) + + if strParameters != None: + if isinstance(strParameters, XElement): + self.FromXML(strParameters) + else: + self.ParseParameters(strParameters) + pass + + def __setversion__(self, vItem): + if dmGlobals.TraceFunctionMessages: print 'Method: dmCollection:__setversion__(objVersion)' + if isinstance(vItem, System.Version): + self.Version = vItem + elif isinstance(vItem, str): + self.Version = System.Version.Parse(vItem) + + def ParseParameters(self, strParameters): + """Parses the file to a collection""" + if dmGlobals.TraceFunctionMessages: print 'Method: dmCollection:ParseParameters(objParameters)' + if File.Exists(strParameters): + try: + self.FromXML(System.Xml.Linq.XDocument.Load(strParameters).Root) + except: + self.Parse(File.ReadAllLines(strParameters)) + pass + + def Parse(self, arrParameters): + """Parses the array of strings to a ruleset collection""" + if dmGlobals.TraceFunctionMessages: print 'Method: dmCollection:Parse(stringarrayParameters)' + nReturn = 0 + while nReturn < arrParameters.Length and not arrParameters[nReturn].startswith(dmGlobals.ENDER): + if arrParameters[nReturn].startswith(dmGlobals.AUTHORHEADER): + self.Name = arrParameters[nReturn].replace(dmGlobals.AUTHORHEADER,'') + nReturn = nReturn + 1 + elif arrParameters[nReturn].startswith(dmGlobals.NOTESHEADER): + nReturn = self.RetrieveNotes(arrParameters, nReturn) + elif arrParameters[nReturn].startswith(dmGlobals.RULESETHEADER) or not arrParameters[nReturn].startswith('#'): + nReturn = self.ParseRuleset(arrParameters, nReturn, self) + elif arrParameters[nReturn].startswith(dmGlobals.GROUPHEADER): + nReturn = self.ParseGroup(arrParameters, nReturn, self) + else: nReturn = nReturn + 1 + pass + + def RetrieveNotes(self, arrParameters, nStartLine): + if dmGlobals.TraceFunctionMessages: print 'Method: dmCollection:RetrieveNotes(stringarrayParameters, intStartLine)' + nReturn = nStartLine + self.Comment = '' + while not arrParameters[nReturn].startswith(NOTESENDER): + self.Comment += arrParameters[nReturn].lstrip('# ') + System.Environment.NewLine + nReturn = nReturn + 1 + pass + + def ProcessBook(self, book, bgWorker): + if dmGlobals.TraceFunctionMessages: + print 'Method: dmCollection:ProcessBook(book, backgroundWorker)' + + strReport = '' + + if not bgWorker.CancellationPending: + strReport = dmContainer.ProcessBook(self, book, bgWorker) + + if dmGlobals.TraceFunctionMessages: + print 'Exiting Method: dmCollection:ProcessBook(book, backgroundWorker)' + + return strReport + + def ToXML(self, elementName): + if dmGlobals.TraceFunctionMessages: + print 'Method: dmCollection:ToXML(stringElementName)' + + baseElement = dmContainer.ToXML(self, elementName) + + baseElement.Add(self.Disabled.XMLSerialize('disabled')) + + return baseElement + + def FromXML(self, element): + if dmGlobals.TraceFunctionMessages: print 'Method: dmCollection:FromXML(xmlElement)' + dmContainer.FromXML(self, element) + self.Disabled = dmGroup(self, element.Element(XName.Get('Disabled'))) + self.__setversion__(element.Attribute(XName.Get('version')).Value) + pass + +class dmGroup(dmContainer): + """a named group of groups and rulesets (derived from dmContainer)""" + + def getFiltersAndDefaults(self): return self.__FiltersAndDefaults + def setFiltersAndDefaults(self, dmrRuleset): self.__FiltersAndDefaults = dmrRuleset + FiltersAndDefaults = property(getFiltersAndDefaults, setFiltersAndDefaults) + + def __init__(self, dmcparent, strParameters=None): + if dmGlobals.TraceFunctionMessages: print 'dmGroup constructor: dmGroup(dmContainerParent, objParameters)' + dmContainer.__init__(self, dmcparent, strParameters) + self.FiltersAndDefaults = dmRuleset(self, None) + + if strParameters != None: + if isinstance(strParameters, XElement): + self.FromXML(strParameters) + else: + self.ParseParameters(strParameters) + pass + + def ParseParameters(self, strParameters): + """Parses Parameters of Group from a string or list of parameters""" + if dmGlobals.TraceFunctionMessages: print 'Method: dmGroup:ParseParameters(objParameters)' + if isinstance(strParameters, str) or isinstance(strParameters, list): + arrParameters = list() + if isinstance(strParameters, str): + arrParameters = strParameters.splitlines() #split string into lines + elif isinstance(strParameters, list): + arrParameters = strParameters + + nReturn = 0 + #Parse Group Info from line + if arrParameters[nReturn].startswith(GROUPHEADER): + GroupInfo = self.ParseNodeInfo(arrParameters[nReturn]) + self.Name = GroupInfo['GROUP'].strip() + if GroupInfo.haskey('COMMENT'): + self.Comment = GroupInfo['COMMENT'].strip() + if GroupInfo.haskey('FILTERSANDDEFAULTS'): + self.FiltersAndDefaults = dmRuleset(self,GroupInfo['FILTERSANDDEFAULTS'].strip()) + #increment nReturn + nReturn = nReturn + 1 + + while nReturn < len(arrParameters) and not arrParameters[nReturn].startswith(GROUPENDER): + if arrParameters[nReturn].startswith(GROUPHEADER): + nReturn = self.ParseGroup(arrParameters, nReturn, self) + elif arrParameters[nReturn].startswith(RULESETHEADER) or not arrParameters[nReturn].startswith('#'): + nReturn = ParseRuleset(arrParameters, nReturn, self) + elif isinstance(strParameters, XElement): + self.FromXML(strParameters) + pass + + def MeetsConditions(self, book): + """Determines if the book matches all Rules in FiltersAndDefaults Ruleset""" + if dmGlobals.TraceFunctionMessages: print 'Method: dmGroup:MeetsConditions(book)' + return self.FiltersAndDefaults.MeetsConditions(book) + + def ProcessBook(self, book, bgWorker): + if dmGlobals.TraceFunctionMessages: + print 'Method: dmGroup:ProcessBook(book, backgroundWorker)' + + strReport = '' + + if self.MeetsConditions(book): + if dmGlobals.TraceGeneralMessages: print 'Book: \'' + book.CaptionWithoutTitle + '\' Meets conditions, Processing.' + strReport = dmContainer.ProcessBook(self, book, bgWorker) + + #groupReport + CompiledReport = '' + if dmGlobals.TraceGeneralMessages: print 'Applying Default actions of group \'' + self.Name + + strTempReport = '' + for action in self.FiltersAndDefaults.Actions: + strTempReport = action.Apply(book) + System.Environment.NewLine + if strTempReport != None and strTempReport != '': + CompiledReport = CompiledReport + strTempReport + if CompiledReport != '': + CompiledReport = 'Group: \'' + self.Name + '\' touched book: ' + book.CaptionWithoutTitle + System.Environment.NewLine + CompiledReport + strReport = strReport + System.Environment.NewLine + CompiledReport + else: + if dmGlobals.TraceGeneralMessages: print 'Conditions set forth by filters of group\'' + self.Name + '\' not met, skiping group.' + + if dmGlobals.TraceFunctionMessages: print 'Exiting Method: dmGroup:ProcessBook(book, backgroundWorker)' + + return strReport + + def ToXML(self, elementName): + if dmGlobals.TraceFunctionMessages: print 'Method: dmGroup:ToXML(stringElementName)' + baseElement = dmContainer.ToXML(self, elementName) + baseElement.Add(self.FiltersAndDefaults.ToXML('filtersanddefaults')) + return baseElement + + def FromXML(self, element): + if dmGlobals.TraceFunctionMessages: print 'Method: dmGroup:FromXML(xmlElement)' + dmContainer.FromXML(self, element) + self.FiltersAndDefaults = dmRuleset(self, element.Element(XName.Get('filtersanddefaults'))) + pass + + def ToString(self): + if dmGlobals.TraceFunctionMessages: print 'Method: dmGroup:ToString()' + strReturn = 'Group: ' + self.Name + ' ' + self.FiltersAndDefaults.HumanizeRules() + return strReturn + +class dmRuleset(dmNode): + """Container for rules and actions""" + + def getRulesetMode(self): return self.__RulesetMode + def setRulesetMode(self, strANDorOR): + if strANDorOR.lower() == 'and': self.__RulesetMode = 'AND' + elif strANDorOR.lower() == 'or': self.__RulesetMode = 'OR' + else: self.__RulesetMode = 'AND' + RulesetMode = property(getRulesetMode, setRulesetMode) + + def getRules(self): return self.__Rules + def setRules(self, lstRules): self.__Rules = List[dmRule](lstRules) + Rules = property(getRules, setRules) + + def getActions(self): return self.__Actions + def setActions(self, lstActions): self.__Actions = List[dmAction](lstActions) + Actions = property(getActions, setActions) + + def __init__(self, dmcparent, strParameters=None): + """initializes ruleset instance""" + if dmGlobals.TraceFunctionMessages: print 'dmRuleset constructor: dmRuleset(objParameters)' + dmNode.__init__(self, dmcparent, strParameters) #calls base initialize which adds base fields + self.RulesetMode = 'AND' #sets ruleset mode by default to AND ParseParameters call (from dmNode) later corrrects if and is used + self.Rules = [] #initializes list of rules + self.Actions = [] #initializes list of actions + + if strParameters != None: + if isinstance(strParameters, XElement): + self.FromXML(strParameters) + else: + self.ParseParameters(strParameters) + pass + + def ParseParameters(self, strParameters): + if dmGlobals.TraceFunctionMessages: print 'Method: dmRuleset:ParseParameters(objParameters)' + if isinstance(strParameters, str): + strParsed = strParameters + """parses ruleset""" #note: this function is called from dmNode initialization + if strParsed.startswith('#@ Invalid Ruleset'): + strParsed = strParsed.split('.', 1)[1] + if strParsed.strip() != '': #if we aren't dealing with an empty string + if strParsed.startswith('|'): #if the ruleset mode is set as OR + self.RulesetMode = 'OR' #specify OR as ruleset mode + rulesAndActions = strParsed.lstrip('|').split('=>',1) #split Rules and Actions + self.ParseItemParameters(rulesAndActions[0], 'Rule') #Parse Rules + self.ParseItemParameters(rulesAndActions[1], 'Action') #Parse Actions + elif isinstance(strParameters, XElement): + self.FromXML(strParameters) + pass + + def ParseItemParameters(self, strRules, strRuleOrAction): + """Parses strRules(string) to Rules Or Actions as specified by strRuleOrAction and adds it to this ruleset accordingly""" + if dmGlobals.TraceFunctionMessages: print 'Method: dmRuleset:ParseItemParameters(stringParameters, stringRuleOrAction)' + parameters = strRules.split('> <') #split into individual rules or actions + for parameter in parameters: #for each item in the created list + if parameter.strip() != '': #if the item is not an empty string + if strRuleOrAction == 'Rule': #if indicated as a Rule + self.Rules.Add(dmRule(self, parameter)) #create and add a dmRule instance to this Ruleset's Rules + elif strRuleOrAction == 'Action': #if indicated as an Action + self.Actions.Add(dmAction(self, parameter)) #create and add a dmAction instance to this Ruleset's Actions + pass + + def MeetsConditions(self, book): + if dmGlobals.TraceFunctionMessages: print 'Method: dmRuleset:MeetsConditions(book)' + bReturn = True + if self.Rules.Count < 1: + if dmGlobals.TraceGeneralMessages: print 'There are no rules defined.' + return True + if self.RulesetMode == 'OR': #if we are using OR mode + if dmGlobals.TraceGeneralMessages: print 'Checking rules in OR Mode' + if len(self.Rules) > 0: + bReturn = False #we need False to be default if we are in OR mode but only if there are rules present. + for rule in self.Rules: #iterate over rules + if rule.Match(book): #we only need one match to decide if conditions are met in OR mode + bReturn = True #set return True as soon as a match found + break #and then exit iteration + else: #if we are using AND mode + if dmGlobals.TraceGeneralMessages: print 'Checking rules in AND Mode' + for rule in self.Rules: #iterate through Rules + if not rule.Match(book): # we only need one non-match to determine conditions are not met + bReturn = False #set return to False as soon as non-match found + break #and then exit iteration + return bReturn #return True or False + + def ApplyActions(self, book): + if dmGlobals.TraceFunctionMessages: print 'Method: dmRuleset:ApplyActions(book)' + strReport = '' + for action in self.Actions: + if dmGlobals.TraceGeneralMessages: print 'Applying Actions...' + strTemp = action.Apply(book) + if strTemp != '': + if strReport != '': strReport = strReport + System.Environment.NewLine + if dmGlobals.TraceGeneralMessages: print 'Value was modified, adding info to report' + strReport = strReport + strTemp + if dmGlobals.TraceFunctionMessages: print 'Exiting Method: dmRuleset:ApplyActions(book)' + return strReport + + def ProcessBook(self, book, bgwProcess): + """Begins Processing of Book with this Ruleset""" + if dmGlobals.TraceFunctionMessages: print 'Method: dmRuleset:ProcessBook(book, backgroundWorker)' + strReport = '' + if dmGlobals.TraceGeneralMessages: print 'Checking rules...' + if self.MeetsConditions(book): #if Rules meet conditions + if dmGlobals.TraceGeneralMessages: + print 'Book met all conditional rules' + print 'Processing Ruleset: ' + self.Name + #create a dictionary of values + strTemp = self.ApplyActions(book) + if strTemp != '': + strReport = System.Environment.NewLine + 'Book: ' + book.CaptionWithoutTitle + ' was touched. ' + self.ToString() + System.Environment.NewLine + strTemp + + return strReport + + def ToString(self): + if dmGlobals.TraceFunctionMessages: print 'Method dmRuleset:ToString()' + strReturn = 'Ruleset: ' + self.Name + ' ' + self.HumanizeRules() + return strReturn + + def HumanizeRules(self): + if dmGlobals.TraceFunctionMessages: print 'Method: dmRuleset:HumanizeRules()' + strReturn = '(' + + ruleCount = 0 + while ruleCount < len(self.Rules): + strReturn = strReturn + self.Rules[ruleCount].ToString() + ruleCount = ruleCount + 1 + if ruleCount < len(self.Rules): strReturn = strReturn + ' ' + self.RulesetMode + ' ' + + strReturn = strReturn + ' => ' + + actionCount = 0 + while actionCount < len(self.Actions): + strReturn = strReturn + self.Actions[actionCount].ToString() + actionCount = actionCount + 1 + + strReturn = strReturn + ')' + return strReturn + + def ToXML(self, elementName): + if dmGlobals.TraceFunctionMessages: print 'Method: dmRuleset:ToXML(stringElementName)' + baseElement = dmNode.ToXML(self, elementName) + baseElement.Attribute['rulesetmode'] = self.RulesetMode + for rule in self.Rules: + baseElement.append(rule.XMLSerialize('rule')) + for action in self.Actions: + baseElement.append(action.XMLSerialize('action')) + pass + + def FromXML(self, element): + if dmGlobals.TraceFunctionMessages: print 'Method: dmRuleset:FromXML(xmlElement)' + dmNode.FromXML(self, element) + self.RulesetMode = element.Attribute(XName.Get('rulesetmode')).Value + for rule in element.Elements(XName.Get('rule')): + self.Rules.append(dmRule(self, rule)) + for action in element.Elements(XName.Get('action')): + self.Actions.append(dmAction(self, action)) + pass + +class dmParameters(dmNode): + + def getField(self): + return self._Field + def setField(self, strCompleteField): + self.ParseField(strCompleteField) + Field = property(getField, setField) + + def getModifier(self): + return self._Modifier + def setModifier(self, strModifier): + self._Modifier = strModifier + Modifier = property(getModifier, setModifier) + + def getValue(self): + return self._Value + def setValue(self, strValue): + self._Value = strValue + Value = property(getValue, setValue) + + @property + def IsCustomField(self): + return self.Field in dmGlobals.READONLYKEYS or not self.Field in dmGlobals.ALLOWEDVALS + + @property + def IsValid(self): + if dmGlobals.TraceFunctionMessages: print 'Property: dmParameters:IsValid' + bReturn = True + + #validation for Actions + if isinstance(self, dmAction): + if (not self.Field in dmGlobals.ALLOWEDVALS): + bReturn = False + if not self.Modifier in dmGlobals.ValidValModifiers(self.Field): + bReturn = False + + #validation for Rules + elif isinstance(self, dmRule): + if (not self.Field in dmGlobals.ALLOWEDVALS): + bReturn = False + if not self.Modifier in dmGlobals.ValidValModifiers(self.Field): + bReturn = False + + #TODO: Determine if the value is valid + if not ValueValid(): + bReturn = false + return bReturn + + """base object for dmRule & dmAction instances""" + def __init__(self, dmnparent, strParameters): + """initializes a dmParameter instance""" + dmNode.__init__(self, dmnparent, strParameters) #calls the base dmNode initializer to initialize further fields + self.Field = '' #initializes the field + self.Modifier = '' #initializes the modifier value + self.Value = '' #initializes the value value + + if strParameters != None: + if isinstance(strParameters, XElement): + self.FromXML(strParameters) + else: + self.ParseParameters(strParameters) + pass + + def ValueValid(self): + if dmGlobals.TraceFunctionMessages: print 'Method: dmParameters:ValueValid()' + bReturn = True + if self.Field in dmGlobals.FIELDSNUMERIC: + #check that string can be converted to this type + try: + dmGlobals.StringToFloat(self.Value) + except: + bReturn = False + if self.Field in dmGlobals.FIELDSDATETIME: + #check that string can be converted to this type + try: + dmGlobals.StringToDate(self.Value) + except: + bReturn = False + if self.Field in dmGlobals.FIELDSLANGUAGEISO: + #TODO: ReadLanguages and ISO abbreviations + #check that string can be converted to this type + try: + pass + except: + pass + if self.Field in dmGlobals.FIELDSBOOL: + #check that string can be converted to this type + try: + dmGlobals.StringToBool(self.Value) + except: + bReturn = False + if self.Field in dmGlobals.FIELDSMANGAYESNO: + #check that string can be converted to this type + try: + dmGlobals.StringToMangaYesNo(self.Value) + except: + bReturn = False + if self.Field in dmGlobals.FIELDSYESNO: + #check that string can be converted to this type + try: + dmGlobals.StringToYesNo(self.Value) + except: + bReturn = False + if self.Field in dmGlobals.FIELDSSTRING or self.Field in dmGlobals.FIELD or self.Field in dmGlobals.FIELDSCUSTOM: + if not self.Field in dmGlobals.FIELDSMULTILINE: + #checks for carriage return info in string values that do not support new lines + if '{newline}' in self.Value: + bReturn = False + + return bReturn; + + def ParseParameters(self, strParameters): + """Parses the string containing info for the parameters""" + if dmGlobals.TraceFunctionMessages: print 'Method: dmParameters:ParseParameters(objParameters)' + if isinstance(strParameters, str): + item = strParameters.strip() #strip whitespace from front of string + + item = item.lstrip('<') #remove all instances '<' from front of string + item = item.rstrip('>') #remove all instances '>' from back of string + + tmpParameters = item.split('.',1) #results in [field, modifier&value] + self.ParseField(tmpParameters[0]) #sets complete field from field value in created list + modfierAndValue = tmpParameters[1].split(':',1) #results in [modifier, value] + + self.Modifier = modfierAndValue[0] #set the modifier + if len(modfierAndValue) > 1: #if a value is present + self.Value = modfierAndValue[1] #set the value accordingly + else: + self.Value = '' #otherwise set Value to empty string for safety purposes + + elif isinstance(strParameters, XElement): + self.FromXML(strParameters) + else: + print 'could not parse Parameter Info' + strParameter + pass + + def FieldConvert(self, strValue, strField=None): + if dmGlobals.TraceFunctionMessages: print 'Method: dmParameters:FieldConvert(stringValue, stringFieldName)' + + FieldValue = self.Field + if strField != None: + FieldValue = strField + + theVal = strValue + try: + if FieldValue in dmGlobals.ALLOWEDVALS: + if FieldValue in dmGlobals.FIELDSLIST and not dmGlobals.IsList(strValue): + theVal = strValue.Split(Array[str](dmGlobals.CRLISTDELIMITER), StringSplitOptions.RemoveEmptyEntries) + elif FieldValue in dmGlobals.FIELDSBOOL and not dmGlobals.IsBool(strValue): + theVal = dmGlobals.StringToBool(strValue) + elif FieldValue in dmGlobals.FIELDSDATETIME and not dmGlobals.IsDateTime(strValue): + theVal = dmGlobals.StringToDate(strValue) + elif FieldValue in dmGlobals.FIELDSNUMERIC and not dmGlobals.IsFloat(strValue): + theVal = dmGlobals.StringToFloat(strValue) + elif FieldValue in dmGlobals.FIELDSMANGAYESNO and not dmGlobals.IsMangaYesNo(strValue): + theVal = dmGlobals.StringToMangaYesNo(strValue) + elif FieldValue in dmGlobals.FIELDSYESNO and not dmGlobals.IsYesNo(strValue): + theVal = dmGlobals.StringToYesNo(strValue) + elif FieldValue in dmGlobals.FIELDSPSUEDONUMERIC and not isinstance(strValue,str): + try: + theVal = strValue.ToString() + except: + pass + #otherwise just return the value + except Exception as ex: + + pass + return theVal + + def GetFieldValue(self, book, strFieldName=None): + if dmGlobals.TraceFunctionMessages: print 'Method: dmParameters:GetFieldValue(book, strFieldName)' + objReturn = None + FieldValue = self.Field + if strFieldName != None: + FieldValue = strFieldName + + if dmGlobals.TraceGeneralMessages: print 'Retrieving value for ' + FieldValue + ' field in comic: ' + book.CaptionWithoutTitle #debug Info + + if FieldValue in dmGlobals.FIELDSLIST: + objReturn = self.GetList(book, FieldValue) + elif not FieldValue in dmGlobals.ALLOWEDVALS and not FieldValue in dmGlobals.ALLOWEDKEYS: + objReturn = self.GetCustomField(book, FieldValue) + else: + objReturn = getattr(book, FieldValue) + + + if dmGlobals.TraceGeneralMessages: + print dmGlobals.ToString(objReturn) + print + return objReturn + + def GetList(self, book, strFieldName): + if dmGlobals.TraceFunctionMessages: print 'Method: dmParameters:GetList(book, strFieldName)' + strList = getattr(book, strFieldName) + if strList == None or strList == '': + strList = [] + else: + strList = strList.split(dmGlobals.CRLISTDELIMITER) + return strList + + def GetCustomField(self, book, strFieldName): + print 'Method: dmParameters:GetCustomField(book, strCustomFieldName)' + strTemp = book.GetCustomValue(strFieldName) + if strTemp == None: + strTemp = '' + return strTemp + + def ParseField(self, strCompleteField=''): + """Sets Field & CustomField values properly""" + if dmGlobals.TraceFunctionMessages: print 'Method: dmParameters:ParseField()' + + if strCompleteField.startswith('Custom'): # if CustomField begins with 'Custom' + tmpRegex = Regex("Custom\((.*?)\)") + self._Field = tmpRegex.Match(strCompleteField).Groups[1].Value #set the Field Value + else: #otherwise + self._Field = strCompleteField #Field value == CompleteField value + pass + + def ToXML(self, elementName): + if dmGlobals.TraceFunctionMessages: print 'Method: dmParameters:ToXML(stringElementName)' + baseElement = XElement(elementName) + baseElement.Add(XAttribute(XName.Get('field'), self.Field)) + baseElement.Add((XName.Get('modifier'), self.Modifier)) + baseElement.Add(XAttribute(XName.Get('value'), self.Value)) + return baseElement + + def FromXML(self, element): + if dmGlobals.TraceFunctionMessages: print 'Method: dmParameters:FromXML(xmlElement)' + self.Field = element.Attribute(XName.Get('field')).Value + self.Modifier = element.Attribute(XName.Get('modifier')).Value + self.Value = element.Attribute(XName.Get('value')).Value + + def ReplaceReferenceStrings(self, strValue, book): + """Replaces references to other fields and newline and tab references""" + if dmGlobals.TraceFunctionMessages: print 'dmAction:ReplaceReferenceStrings(self, strValue, book)' + strNewValue = strValue + + strNewValue = strNewValue.replace('{newline}', System.Environment.NewLine) + strNewValue = strNewValue.replace('{tab}', ' ') + + #find field (including custom) references and replace + for x in Regex.Matches(strNewValue, "\\{([^}]+?)}"): + strNewValue = strNewValue.replace(x.Groups[0].Value, self.GetFieldValue(book, x.Groups[1].Value)) + + return strNewValue + + def ToString(self): + if dmGlobals.TraceFunctionMessages: print 'Method: dmParameters:ToString()' + strReturn = self.Field + ' ' + self.Modifier.upper() + ' \'' + self.Value + '\'' + return strReturn + +class dmRule(dmParameters): + """defines a restriction on whether or not defined actions should be applied""" + def __init__(self, dmnparent, strParameters): + """initializes a dmRule instance""" + if dmGlobals.TraceFunctionMessages: print 'dmRule constructor: dmRule(dmNodeParent, objParameters)' + dmParameters.__init__(self, dmnparent, strParameters) #call initialization done in the dmParameters base instance + pass + + def Match(self, book): + """Determines if the rule matches the book file (returns True or False)""" + if dmGlobals.TraceFunctionMessages: print 'Method: dmRule:Match(book)' + return getattr(self, self.Modifier)(book) #sends the book to the designated (by self.Modifier) function to determine if the rule matches + + def Is(self, book): + if dmGlobals.TraceFunctionMessages: print 'Method: dmRule:Is(book)' + + getValue = self.GetFieldValue(book, self.Field) #get Value from book + compareValue = self.FieldConvert(self.ReplaceReferenceStrings(self.Value, book) ,self.Field) #value to compare + + if self.Field in dmGlobals.FIELDSLIST: #deal with list items as individual items + + if len(compareValue) == len(getValue): #only continue if lists are same legnth + count = 0 + for item in compareValue: #iterate through compare list items + for val in getValue: #iterate through book list items + if val.lower() == item.lower(): #compare lowercase list items from book (val) to compare list items (item) + count = count + 1 #if match increment count + if count == len(getValue): #if count ends up equal between book list items and compare list items + return True #set true + else: + if isinstance(getValue, str): + if getValue.lower() == compareValue.lower(): + return True + else: + if getValue == compareValue: #if values match + return True #set true + + return False #if everything else fails set false + + def Not(self, book): + if dmGlobals.TraceFunctionMessages: print 'Method: dmRule:Not(book)' + return not self.Is(book) #return inverse of 'Is(book)' + + def IsAnyOf(self, book): + """Available for string languageISO, psuedonumeric, and numeric""" + if dmGlobals.TraceFunctionMessages: print 'Method: dmRule:IsAnyOf(book)' + + getValue = self.GetFieldValue(book, self.Field) #get Value from book + compareValue = self.ReplaceReferenceStrings(self.Value, book).split(dmGlobals.DMLISTDELIMITER) #value to compare as list + + for word in compareValue: + if isinstance(getValue, str): #if dealing with string + if getValue.lower() == word.lower(): #compare lowercase + return True + if getValue == self.FieldConvert(word, self.Field): + return True + return False + + def NotIsAnyOf(self, book): + if dmGlobals.TraceFunctionMessages: print 'Method: dmRule:NotIsAny(book)' + return not self.IsAnyOf(book) + + def Contains(self, book): + """Only applicable with string and list""" + if dmGlobals.TraceFunctionMessages: print 'Method: dmRule:Contains(book)' + + getValue = self.GetFieldValue(book, self.Field) #get Value from book + compareValue = self.ReplaceReferenceStrings(self.Value, book) #value to compare + + if self.Field in dmGlobals.FIELDSLIST: #search as string list + for check in getValue: + if compareValue.lower() in check.lower(): + return True + else: #search as string + if compareValue.lower() in getValue.lower(): + return True + return False + + def NotContains(self, book): + """Only applicable with string and list""" + if dmGlobals.TraceFunctionMessages: print 'Method: dmRule:NotContains(book)' + return not self.Contains(book) + + def ContainsAnyOf(self, book): + """Only applicable with string and list""" + if dmGlobals.TraceFunctionMessages: print 'Method: dmRule:ContainsAnyOf(book)' + + getValue = self.GetFieldValue(book, self.Field) #get Value from book + compareValue = self.ReplaceReferenceStrings(self.Value, book).split(dmGlobals.DMLISTDELIMITER) #value to compare + + for compareItem in compareValue: + if self.Field in dmGlobals.FIELDSLIST: #compare list against list + for getItem in getValue: #compare list items as lowercase + if compareItem.lower() in getItem.lower(): + return True #return true at first instance of match + else: #compare list against string + if compareItem.lower() in getValue.lower(): #compare string item against list item + return True #return true at first instance of match + return False #all else failing return false + + def NotContainsAnyOf(self, book): + """Only applicable with string and list""" + if dmGlobals.TraceFunctionMessages: print 'Method: dmRule:NotContainsAnyOf(book)' + return not self.ContainsAnyOf(book) + + def ListContains(self, book): + """Only applicable with string and list""" + if dmGlobals.TraceFunctionMessages: print 'Method: dmRule:Contains(book)' + + for check in getValue: + if check.lower() == compareValue.lower(): + return True + + def NotListContains(self, book): + return not self.ListContains(book) + + def ListContainsAnyOf(self, book): + """Only applicable with string and list""" + if dmGlobals.TraceFunctionMessages: print 'Method: dmRule:ContainsAnyOf(book)' + + getValue = self.GetFieldValue(book, self.Field) #get Value from book + compareValue = self.ReplaceReferenceStrings(self.Value, book).split(dmGlobals.DMLISTDELIMITER) #value to compare + + for compareItem in compareValue: + if self.Field in dmGlobals.FIELDSLIST: #compare list against list + for getItem in getValue: #compare list items as lowercase + if compareItem.lower() in getItem.lower(): + return True #return true at first instance of match + else: #compare list against string + if compareItem.lower() in getValue.lower(): #compare string item against list item + return True #return true at first instance of match + + def NotListContainsAnyOf(self, book): + return not self.ListContainsAnyOf(book) + + def ListContainsAllOf(self, book): + + pass + + def ListContainsAllOf(self, book): + return not self.ListContainsAllOf(book) + pass + + + + def ContainsAllOf(self, book): + """Only applicable with string and list""" + if dmGlobals.TraceFunctionMessages: print 'Method: dmRule:ContainsAllOf(book)' + + getValue = self.GetFieldValue(book, self.Field) #get Value from book + compareValue = self.ReplaceReferenceStrings(self.Value, book).split(dmGlobals.DMLISTDELIMITER) #value to compare + + all = True + for compareItem in compareValue: + if self.Field in dmGlobals.FIELDSLIST: #compare list against list + for getItem in getValue: #compare list items as lowercase + all &= compareItem.lower() in getItem.lower() + else: #compare list against string + all &= compareItem.lower() in getValue.lower() #compare string item against list item + return all + + def NotContainsAllOf(self, book): + """Only applicable with string and list""" + if dmGlobals.TraceFunctionMessages: print 'Method: dmRule:NotContainsAllOf(book)' + return not self.ContainsAllOf(book) + + def StartsWith(self, book): + """Only applicable with string""" + if dmGlobals.TraceFunctionMessages: print 'Method: dmRule:StartsWith(book)' + + getValue = self.GetFieldValue(book, self.Field) #get Value from book + compareValue = self.ReplaceReferenceStrings(self.Value, book) #value to compare + + return getValue.lower().startswith(compareValue.lower()) + + def NotStartsWith(self, book): + """Only applicable with string""" + if dmGlobals.TraceFunctionMessages: print 'Method: dmRule:NotStartsWith(book)' + return not self.StartsWith(book) + + def StartsWithAnyOf(self, book): + """Only applicable with string""" + if dmGlobals.TraceFunctionMessages: print 'Method: dmRule:StartsWithAnyOf(book)' + + getValue = self.GetFieldValue(book, self.Field) #get Value from book + compareValue = self.ReplaceReferenceStrings(self.Value, book).split(dmGlobals.DMLISTDELIMITER) #value to compare + + for compareItem in compareValue: #compare each item until truth found + if getValue.lower().startswith(compareItem.lower()): #check if list item at the beginning of string + return True # return true at first instance of match + + return False + + def NotStartsWithAnyOf(self, book): + """Only applicable with string""" + if dmGlobals.TraceFunctionMessages: print 'Method: dmRule:NotNotStartsWithAnyOf(book)' + return not self.StartsWithAnyOf(book) + + def Greater(self, book): + """Only applicable with numeric, psuedo numeric, and date""" + if dmGlobals.TraceFunctionMessages: print 'Method: dmRule:Greater(book)' + + getValue = self.GetFieldValue(book, self.Field) #get Value from book + compareValue = self.FieldConvert(self.Value, self.Field) #value to compare + + if self.Field in dmGlobals.FIELDSNUMERIC: + try: + compareValue = dmGlobals.StringToFloat(compareValue) + return getValue > compareValue + except: + raise Exception('could not convert \'' + self.Value + '\' to Float') + elif self.Field in dmGlobals.FIELDSPSUEDONUMERIC: + count = 0 + prefixGet = '' + prefixCompare = '' + numberCompare = '' + numberGet = '' + suffixGet = '' + suffixCompare = '' + + #seperate prefixes and suffixes + while count < len(getValue) and not getValue[count].isdigit(): + prefixGet = prefixGet + getValue[count] + count = count + 1 + while count < len(getValue) and getValue[count].isdigit(): + numberGet = numberGet + getValue[count] + count = count + 1 + while count < len(getValue): + suffixGet = suffixGet + getValue[count] + count = count + 1 + + count = 0 + + while count < len(compareValue) and not compareValue[count].isdigit(): + prefixCompare = prefixCompare + compareValue[count] + count = count + 1 + while count < len(compareValue) and compareValue[count].isdigit(): + numberCompare = numberCompare + compareValue[count] + count = count + 1 + while count < len(compareValue): + suffixCompare = suffixCompare + compareValue[count] + count = count + 1 + + try: + if prefixCompare == prefixGet: #if prefixes match + if numberGet == numberCompare: + return suffixGet > suffixCompare + else: + return dmGlobals.StringToFloat(numberGet) > dmGlobals.StringToFloat(numberCompare) + else: #return comparison of prefixes + return prefixGet > prefixCompare + + return getValue > compareValue + except: + raise Exception('could not convert \'' + self.Value + '\' to Float') + + elif self.Field in dmGlobals.FIELDSDATETIME: + try: + compareValue = dmGlobals.StringToDate(compareValue) + return getValue > compareValue + except: + raise Exception('could not convert \'' + self.Value + '\' to Date') + + return False + + def GreaterEq(self, book): + """Only applicable with numeric, psuedo numeric, and date""" + if dmGlobals.TraceFunctionMessages: print 'Method: dmRule:GreaterEq(book)' + return self.Greater(book) or self.Is(book) + + def Less(self, book): + """Only applicable with numeric, psuedo numeric, and date""" + if dmGlobals.TraceFunctionMessages: print 'Method: dmRule:Less(book)' + + getValue = self.GetFieldValue(book, self.Field) #get Value from book + compareValue = self.FieldConvert(self.Value, self.Field) #value to compare + + if self.Field in dmGlobals.FIELDSNUMERIC: + try: + compareValue = dmGlobals.StringToFloat(compareValue) + return getValue < compareValue + except: + raise Exception('could not convert \'' + self.Value + '\' to Float') + elif self.Field in dmGlobals.FIELDSPSUEDONUMERIC: + count = 0 + prefixGet = '' + prefixCompare = '' + numberCompare = '' + numberGet = '' + suffixGet = '' + suffixCompare = '' + + #seperate prefixes and suffixes + while count < len(getValue) and not getValue[count].isdigit(): + prefixGet = prefixGet + getValue[count] + count = count + 1 + while count < len(getValue) and getValue[count].isdigit(): + numberGet = numberGet + getValue[count] + count = count + 1 + while count < len(getValue): + suffixGet = suffixGet + getValue[count] + count = count + 1 + + count = 0 + + while count < len(compareValue) and not compareValue[count].isdigit(): + prefixCompare = prefixCompare + compareValue[count] + count = count + 1 + while count < len(compareValue) and compareValue[count].isdigit(): + numberCompare = numberCompare + compareValue[count] + count = count + 1 + while count < len(compareValue): + suffixCompare = suffixCompare + compareValue[count] + count = count + 1 + + try: + if prefixCompare == prefixGet: #if prefixes match + if numberGet == numberCompare: #and number matches + return suffixGet < suffixCompare #return suffix comparison + else: + return dmGlobals.StringToFloat(numberGet) < dmGlobals.StringToFloat(numberCompare) #return Number comparision + else: #return comparison of prefixes + return prefixGet < prefixCompare + except: + raise Exception('could not convert \'' + self.Value + '\' to Float') + + elif self.Field in dmGlobals.FIELDSDATETIME: + try: + compareValue = dmGlobals.StringToDate(compareValue) + return getValue < compareValue + except: + raise Exception('could not convert \'' + self.Value + '\' to Date') + + return False + + def LessEq(self, book): + """Only applicable with numeric, psuedo numeric, and date""" + if dmGlobals.TraceFunctionMessages: print 'Method: dmRule:LessEq(book)' + return self.Less(book) or self.Is(book) + + def Range(self, book): + """Only applicable with numeric, psuedo numeric, and date""" + if dmGlobals.TraceFunctionMessages: print 'Method dmRule:Range(book)' + + getValue = self.GetFieldValue(book, self.Field) + + minVal = self.Value.split(dmGlobals.DMLISTDELIMITER)[0] + maxVal = self.Value.split(dmGlobals.DMLISTDELIMITER)[1] + + if (self.Field in dmGlobals.FIELDSNUMERIC) or (self.Field in dmGlobals.FIELDSPSUEDONUMERIC): + minVal = dmGlobals.StringToFloat(minVal) + maxVal = dmGlobals.StringToFloat(maxVal) + elif self.Field in dmGlobals.FIELDSDATETIME: + minVal = System.DateTime.Parse(minVal) + maxVal = System.DateTime.Parse(minVal + ' 23:59:59') + if getValue >= minVal and getValue <= maxVal: + return True + return False + + def NotRange(self, book): + """Only applicable with numeric, psuedo numeric, and date""" + if dmGlobals.TraceFunctionMessages: print 'Method: dmRule:NotRange(book)' + return not Range(book) + + def RegEx(self, book): + """Only applicable with string""" + if dmGlobals.TraceFunctionMessages: print 'Method: dmRule:RegEx(book)' + + getValue = self.GetFieldValue(book, self.Field) + compareValue = self.ReplaceReferenceStrings(self.Value, book) + + regExp = Regex(compareValue, RegexOptions.Singleline | RegexOptions.IgnoreCase) + + return regExp.Match(getValue).Success + + def NotRegEx(self, book): + """Only applicable with string""" + if dmGlobals.TraceFunctionMessages: print 'Method: dmRule:NotRegEx(book)' + return not self.RegEx(book) + +class dmAction(dmParameters): + def __init__(self, dmnparent, strParameters): + if dmGlobals.TraceFunctionMessages: print 'dmAction constructor: dmAction(dmRulesetParent, objParameters)' + dmParameters.__init__(self, dmnparent, strParameters) + pass + + def Apply(self, book): + if dmGlobals.TraceFunctionMessages: print 'Method: dmAction:Apply(book)' + strReport = getattr(self, self.Modifier)(book) #send book to function specified by Modifier + return strReport + + def SetFieldValue(self, book, newValue, strField=None): + """Determines the proper write to book technique (Standard or Custom Field) and applies value""" + if dmGlobals.TraceFunctionMessages: print 'Method: dmAction:SetValue(book, objNewValue, stringFieldName)' + + FieldValue = self.Field + + if strField != None: + FieldValue = strField + + previousVal = self.GetFieldValue(book, FieldValue) + + newVal = newValue + + strReport = '' + if FieldValue in dmGlobals.FIELDSLIST: + if dmGlobals.SortLists: + newVal.sort() + newVal = dmGlobals.CRLISTDELIMITER.join(newVal) + previousVal = dmGlobals.CRLISTDELIMITER.join(previousVal) + + if FieldValue in dmGlobals.ALLOWEDVALS: + try: + if FieldValue in dmGlobals.FIELDSNUMERIC: + setattr(book, FieldValue, dmGlobals.StringToFloat(newVal)) #convert to float + else: + setattr(book, FieldValue, newVal.ToString()) + #prepare the report + strReport = ' Field: ' + FieldValue + ' Action: ' + self.ToString() + strReport = strReport + System.Environment.NewLine + ' Previous Value: ' + dmGlobals.ToString(previousVal) + strReport = strReport + System.Environment.NewLine + ' New Value: ' + dmGlobals.ToString(newVal) + '\r\n' + except Exception as er: + #report errors instead + strReport = ' An unexpected error occured in Action: ' + self.ToString() + ' Parent Ruleset : ' + self.Parent.Name + if isinstance(er, dmConversionError): + strReport = strReport + ' Error' + er.msg + pass + else: + self.SetCustomField(book, FieldValue, newVal) + #prepare the report + if strReport != '': strReport = System.Environment.NewLine + strReport = ' CustomField: ' + self.Field + ' Action: ' + self.ToString() + strReport = strReport + System.Environment.NewLine + ' Previous Value: ' + dmGlobals.ToString(previousVal) + strReport = strReport + System.Environment.NewLine + ' New Value: ' + dmGlobals.ToString(newVal) + return strReport + + def SetCustomField(self, book, strCustomFieldName, strNewValue): + """Sets 'CustomField' value of book to strNewValue""" + if dmGlobals.TraceFunctionMessages: print 'SetCustomField(book, stringFieldName, stringNewValue)' + book.SetCustomValue(strCustomFieldName, strNewValue) + pass + + + def GetAppendedField(self, strFieldName, book, strAppendString): + objReturn = self.GetFieldValue(book, strFieldName) + if strFieldName in dmGlobals.FIELDSLIST: + objReturn.append(strAppendString) + elif strFieldName in dmGlobals.FIELDSMULTILINE: + objReturn = objReturn + System.Environment.NewLine + strAppendString + else: + objReturn = objReturn + ' ' + strAppendString + return objReturn + + def SetValue(self, book): + """valid with all action value types""" + if dmGlobals.TraceFunctionMessages: print 'Method: dmAction:SetValue(book)' + if dmGlobals.TraceGeneralMessages: print 'book = ' + book.CaptionWithoutTitle + strReport = '' + + setValue = self.ReplaceReferenceStrings(self.Value, book) #get new Value from local value replacing reference strings + + setValue = self.FieldConvert(setValue, self.Field) #convert setValue to proper object class + + strReport = self.SetFieldValue(book, setValue) + + return strReport + + def Add(self, book): + if dmGlobals.TraceFunctionMessages: print 'Method: dmRule:Add(book)' + + getValue = self.GetFieldValue(book, self.Field) #copy current value + setValue = self.ReplaceReferenceStrings(self.Value,book).split(dmGlobals.DMLISTDELIMITER) #copy value replacing book variables with their values + + strReport = '' + newVal = getValue + + if self.Field in dmGlobals.FIELDSLIST: + addItem = True + for value in setValue: + for existingItem in newVal: + if value.lower() == existingItem.lower(): + addItem = False + break + if addItem: + newVal.Add(value) + else: #since this is only a valid modifier for list and string assume string + for item in setValue: + newVal = newVal + item + + strReport = self.SetFieldValue(book, newVal) #finally set the new value + return strReport + + def Remove(self, book): + if dmGlobals.TraceFunctionMessages: print 'Method: dmAction:Remove(book)' + + getValue = self.GetFieldValue(book, self.Field) #copy current value + setValue = self.ReplaceReferenceStrings(self.Value,book).split(dmGlobals.DMLISTDELIMITER) #copy value replacing book variables with their values + + strReport = '' + newVal = '' + + #set values for list items + if self.Field in dmGlobals.FIELDSLIST: #if the type of field is a list + tmpList = [] #create a list to transfer values to + + for item in getValue: #iterate over the book's list items + addItem = True + for val in setValue: #iterate through the values to remove + if val.lower() == item.lower(): #compare value to remove to book's list item if it does not match + addItem = False + break + if addItem: + tmpList.append(item) #add item to list + + setValue = tmpList + else: #if it's not a list item consider it a string (since only strings and lists have this modifier available) + for val in setValue: #iterate through list of values to remove + newValue = getValue + while val.lower() in newValue.lower(): #as long as string contains the value to remove + idx = newValue.lower().find(val.lower()) #find the index of the value to remove + newValue = newValue.Remove(idx, len(val)) #remove len(val) characters starting from idx + + setValue = newValue + + strReport = self.SetFieldValue(book, setValue) + + + return strReport #return Action Report + + def Replace(self, book): + if dmGlobals.TraceFunctionMessages: print 'Method: dmAction:Replace(book)' + + getValue = self.GetFieldValue(book, self.Field) + setValue = self.ReplaceReferenceStrings(self.Value, book).split(dmGlobals.DMLISTDELIMITER) + newValue = getValue + + + finditem = setValue[0] + replaceitem = setValue[1] + + if self.Field in dmGlobals.FIELDSLIST: + oldList = self.GetFieldValue(book, self.Field) + newList = [] + if not dmGlobals.COMPARE_CASE_SENSITIVE: + for getItem in getValue: + if getItem.lower() == finditem.lower(): + newList.Add(replaceitem) + break + else: + newList.Add(getItem) + else: + for getItem in getValue: + if getItem == finditem: + newList.Add(replaceitem) + break + else: + newList.Add(getItem) + newValue = newList + + else: + idx = 0 + if not dmGlobals.COMPARE_CASE_SENSITIVE: + while finditem.lower() in newValue: + idx = newValue.lower().find(finditem.lower()) #find the index of the value to replace + newValue = newValue.Remove(idx, len(finditem)) + newValue = newValue.Insert(idx, replaceitem) + else: + while finditem.lower() in newValue: + idx = newValue.find(finditem) #find the index of the value to replace + newValue = newValue.Remove(idx, len(finditem)) + newValue = newValue.Insert(idx, replaceitem) + + + strReport = self.SetFieldValue(book, newValue) + + + return strReport + + def Calc(self, book): + """valid for numeric and psuedonumeric""" + if dmGlobals.TraceFunctionMessages: print 'Method: dmAction.Calc(book)' + + setValue = self.ReplaceReferenceStrings(self.Value, book) + + myVal = eval(setValue) + + strReport = self.SetFieldValue(book, myVal) + + return strReport + + def RegexReplace(self, book): + if dmGlobals.TraceFunctionMessages: print 'Method: dmAction:RegexReplace(book)' + + getValue = self.GetFieldValue(book, self.Field) + setValue = self.ReplaceReferenceStrings(self.Value, book).split(dmGlobals.DMLISTDELIMITER, 1) + + strReport = '' + + setPattern = setValue[0] + setFormat = setValue[1] + + RegExp = Regex(setPattern, RegexOptions.IgnoreCase | RegexOptions.Singleline) + + myString = getValue + while RegExp.Match(myString).Success: + myString = RegExp.Replace(myString, setFormat) + + strReport = self.SetFieldValue(book, myString) + + return strReport + + def RegExVarReplace(self, book): + if dmGlobals.TraceFunctionMessages: print 'Method: dmAction:RegexVarReplace(book)' + myString = self.GetFieldValue(book, self.Field) #get the value of the Field in the book + myVal = self.ReplaceReferenceStrings(self.Value, book) #replace reference strings on the proposed value + + strReport = '' #initialize report + + + RegExp = Regex(myVal, RegexOptions.IgnoreCase) #compile the Regex + + matchItem = RegExp.Match(myString) #get the match + if matchItem.Success: + if dmGlobals.TraceGeneralMessages: print 'Book: ' + book.CaptionWithoutTitle + ' field ' + self.Field + ' matched Regex ' + myVal #print Debug Info + if dmGlobals.TraceGeneralMessages: print ' book.' + self.Field + '= ' + dmGlobals.ToString(myString) + if dmGlobals.TraceGeneralMessages: print ' Regex Match = ' + matchItem.Groups[0].Value + + + #iterate over capture names and apply + for groupName in RegExp.GetGroupNames(): + if dmGlobals.TraceGeneralMessages: print 'attempting to apply values to specified fields. WARNING: any unnamed captures will cause an error' + try: + if groupName != '0': #eliminate possible error of group zero being used (group zero is the whole match text) + strFieldName = groupName #get fieldname that's being changed + strNewValue = matchItem.Groups[groupName].Value #get the text that will replace the field + + strReport = strReport + self.SetFieldValue(book, strNewValue, strFieldName) #replace the field + except Exception as er: + + pass + return strReport + + def RegExVarAppend(self, book): + if dmGlobals.TraceFunctionMessages: print 'Method: dmAction:RegexVarAppend(book)' + + + myString = self.GetFieldValue(book, self.Field) #get the value of the Field in the book + myVal = self.ReplaceReferenceStrings(self.Value, book) #replace reference strings on the proposed value + + strReport = '' #initialize report + + + RegExp = Regex(myVal, RegexOptions.IgnoreCase) #compile the Regex + + matchItem = RegExp.Match(myString) #get the match + if matchItem.Success: + if dmGlobals.TraceGeneralMessages: print 'Book: ' + book.CaptionWithoutTitle + ' field ' + self.Field + ' matched Regex ' + myVal #print Debug Info + if dmGlobals.TraceGeneralMessages: print ' book.' + self.Field + '= ' + dmGlobals.ToString(myString) + if dmGlobals.TraceGeneralMessages: print ' Regex Match = ' + matchItem.Groups[0].Value + + + #iterate over capture names and apply + for groupName in RegExp.GetGroupNames(): + if dmGlobals.TraceGeneralMessages: print 'attempting to apply values to specified fields. WARNING: any unnamed captures will cause an error' + try: + if groupName != '0': #eliminate possible error of group zero being used (group zero is the whole match text) + strFieldName = groupName #get fieldname that's being changed + strNewValue = '' + + strNewValue = self.GetAppendedField(strFieldName, book, matchItem.Groups[groupName].Value) #get the text that will replace the field + strOldValue = self.GetFieldValue + strReport = strReport + self.SetFieldValue(book, strNewValue, strFieldName) #replace the field + + except Exception as er: + + pass + return strReport + + + def RemoveLeading(self, book): + if dmGlobals.TraceFunctionMessages: print 'Method: dmAction:RemoveLeading(book)' + + myString = self.GetFieldValue(book) + myVal = self.ReplaceReferenceStrings(self.Value, book) + + if myString.lower().startswith(myVal.lower()): + myString = myString.Remove(0, len(myVal)) + + strReport = self.SetFieldValue(book, myString) + + return strReport diff --git a/dmGlobals.py b/dmGlobals.py index 9be4a1e..3f089ce 100644 --- a/dmGlobals.py +++ b/dmGlobals.py @@ -1,472 +1,472 @@ -# some variables for global use -import clr -import System -from System.IO import Path, FileInfo -import iniReadWrite -from System import Array -from System import StringSplitOptions -from iniReadWrite import * -from System.Collections.Generic import Dictionary -#clr.AddReference("ComicRack.Engine") -from cYo.Projects.ComicRack.Engine import MangaYesNo, YesNo - - -############Set Paths############## -FOLDER = FileInfo(__file__).DirectoryName + Path.DirectorySeparatorChar.ToString() -IMGFOLDER = FOLDER + 'images' + Path.DirectorySeparatorChar.ToString() -DATFILE = Path.Combine(FOLDER, 'dataMan.dat') #can load 1.24 text files or 2.3.1 xml files saves as xml -SAMPLEFILE = Path.Combine(FOLDER, 'dataManSample.dat') -INIFILE = Path.Combine(FOLDER, 'dataMan.ini') -USERINI = Path.Combine(FOLDER, 'user.ini') -BAKFILE = Path.Combine(FOLDER, 'dataMan.bak') -ERRFILE = Path.Combine(FOLDER, 'dataMan.err') -TMPFILE = Path.Combine(FOLDER, 'dataMan.tmp') -LOGFILE = Path.Combine(FOLDER, 'dataMan.log') -CHKFILE = Path.Combine(FOLDER, 'dataMan.chk') # will be created once the configuration is saved -GUIEXE = Path.Combine(FOLDER, 'crdmgui.exe') - -##############End Set Paths############## - -################Set Constant variables############## - -CRLISTDELIMITER = ', ' - -GROUPHEADER = '#@ GROUP ' -RULESETHEADER = '#@ NAME ' -GROUPENDER = '#@ END_GROUP' - -ENDER = '#@ END_RULES' -AUTHORHEADER = '#@ AUTHOR' -NOTESHEADER = '#@ NOTES' - -########################### Images ############################# - -ICON_SMALL = Path.Combine(IMGFOLDER, 'dataMan16.ico') -ICON = Path.Combine(IMGFOLDER, 'dataMan.ico') -IMAGE = Path.Combine(IMGFOLDER, 'dataMan.png') -IMAGESEARCH = Path.Combine(IMGFOLDER, 'search.png') -IMAGEADD = Path.Combine(IMGFOLDER, 'yes.png') -IMAGEAPPLY = Path.Combine(IMGFOLDER, 'Apply.png') -IMAGETRASH = Path.Combine(IMGFOLDER, 'Trash.png') -IMAGEDELETE_SMALL = Path.Combine(IMGFOLDER, 'erase.png') -IMAGEDOWN = Path.Combine(IMGFOLDER, 'down.png') -IMAGELIGHTNING = Path.Combine(IMGFOLDER, 'lightning.png') -IMAGETEXT = Path.Combine(IMGFOLDER, 'text.png') -DONATE = 'https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=UQ7JZY366R85S' -WIKI = 'http://code.google.com/p/cr-data-manager/' -MANUAL = 'http://code.google.com/p/cr-data-manager/downloads/list' - -COMPARE_CASE_SENSITIVE = ReadKeyAsBool(INIFILE, 'CaseSensitive') - - -#############End set constant variables################## - -######################Read From dataman.ini############################### -VERSION = System.Version(ReadKey(INIFILE,'Version')) -DMLISTDELIMITER = ReadKey(INIFILE, 'ListDelimiter') -DATEFORMAT = ReadKey(INIFILE, 'DateTimeFormat') - -####FIELDTYPES AND ALLOWED MODIFIERS######### -ALLOWEDKEYS = ReadKeyAsStringList(INIFILE, 'allowedKeys') -ALLOWEDVALS = ReadKeyAsStringList(INIFILE, 'allowedVals') -READONLYKEYS = ReadKeyAsStringList(INIFILE, 'ReadOnlyKeys') - -ALLOWEDKEYMODIFIERS = ReadKeyAsStringList(INIFILE, 'allowedKeyModifiers') -ALLOWEDVALMODIFIERS = ReadKeyAsStringList(INIFILE, 'allowedValModifiers') - -FIELDSSTRING = ReadKeyAsStringList(INIFILE, 'stringKeys') -ALLOWEDKEYMODIFIERSSTRING = ReadKeyAsStringList(INIFILE, 'allowedKeyModifiersString') -ALLOWEDVALMODIFIERSSTRING = ReadKeyAsStringList(INIFILE, 'allowedValModifiersString') - -FIELDSLIST = ReadKeyAsStringList(INIFILE, 'multiValueKeys') -ALLOWEDKEYMODIFIERSLIST = ReadKeyAsStringList(INIFILE, 'allowedKeyModifiersMulti') -ALLOWEDVALMODIFIERSLIST = ReadKeyAsStringList(INIFILE, 'allowedValModifiersMulti') - -FIELDSDATETIME = ReadKeyAsStringList(INIFILE, 'dateTimeKeys') -ALLOWEDKEYMODIFIERSDATETIME = ReadKeyAsStringList(INIFILE, 'allowedKeyModifierDateTime') -ALLOWEDVALMODIFIERSDATETIME = ReadKeyAsStringList(INIFILE, 'allowedValModifierDateTime') - -FIELDSLANGUAGEISO = ReadKeyAsStringList(INIFILE, 'languageISOKeys') -ALLOWEDKEYMODIFIERSLANGUAGEISO = ReadKeyAsStringList(INIFILE, 'allowedKeyModifierLanguageISO') -ALLOWEDVALMODIFIERSLANGUAGEISO = ReadKeyAsStringList(INIFILE, 'allowedValModifierLanguageISO') - -FIELDSMANGAYESNO = ReadKeyAsStringList(INIFILE, 'mangaYesNoKeys') -ALLOWEDKEYMODIFIERSMANGAYESNO = ReadKeyAsStringList(INIFILE, 'allowedKeyModifierMangaYesNo') -ALLOWEDVALMODIFIERSMANGAYESNO = ReadKeyAsStringList(INIFILE, 'allowedValModifierMangaYesNo') - -FIELDSYESNO = ReadKeyAsStringList(INIFILE, 'yesNoKeys') -ALLOWEDKEYMODIFIERSYESNO = ReadKeyAsStringList(INIFILE, 'allowedKeyModifierYesNo') -ALLOWEDVALMODIFIERSYESNO = ReadKeyAsStringList(INIFILE, 'allowedValModifierYesNo') - -FIELDSBOOL = ReadKeyAsStringList(INIFILE, 'boolKeys') -ALLOWEDKEYMODIFIERSBOOL = ReadKeyAsStringList(INIFILE, 'allowedKeyModifierBool') -ALLOWEDVALMODIFIERSBOOL = ReadKeyAsStringList(INIFILE, 'allowedValModifierBool') - -ALLOWEDKEYMODIFIERSCUSTOM = ReadKeyAsStringList(INIFILE, 'allowedKeyModifierString') -ALLOWEDVALMODIFIERSCUSTOM = ReadKeyAsStringList(INIFILE, 'allowedValModifierString') - -FIELDSNUMERIC = ReadKeyAsStringList(INIFILE, 'numericalKeys') -FIELDSPSUEDONUMERIC = ReadKeyAsStringList(INIFILE, 'pseudoNumericalKeys') -ALLOWEDKEYMODIFIERSNUMERIC = ReadKeyAsStringList(INIFILE, 'allowedKeyModifiersNumeric') -ALLOWEDVALMODIFIERSNUMERIC = ReadKeyAsStringList(INIFILE, 'allowedValModifiersNumeric') - -REGEXVARREPLACEKEYS = ReadKeyAsStringList(INIFILE, 'regExVarReplaceFields') - -MULTIPARAMMODIFIERS = ReadKeyAsStringList(INIFILE, 'multipleParamModifiers') - -FIELDSMULTILINE = ReadKeyAsStringList(INIFILE, 'multiLineKeys') -####END FIELDTYPES AND ALLOWED MODIFIERS######### -#################End read From dataman.ini############################ - -#####################Read From User.ini####################### -BreakAfterFirstError = ReadKeyAsBool(USERINI, "BreakAfterFirstError") -TraceGeneralMessages = ReadKeyAsBool(USERINI, 'TraceGeneralMessages') -TraceFunctionMessages = ReadKeyAsBool(USERINI, 'TraceFunctionMessages') -SortLists = ReadKeyAsBool(USERINI, 'SortLists') -#############type conversion utilities ######################## - -def StringToDate(strDate): - if strDate == '': - return System.DateTime(1,1,1) - return System.DateTime.Parse(strDate) - -def IsDateTime(value): - return isinstance(value, System.DateTime) - -def StringToInt(strNumber): - if strNumber == '': - return int(-1) - return int(strNumber) - -def IsInt(value): - return isinstance(value, System.Int32) - -def StringToFloat(strFloat): - fValue = float(-1) - fValue = float(strFloat) - return fValue - -def IsFloat(value): - return isinstance(value, float) - -def CRStringToList(strList): - return strList.Split(Array[str](CRLISTDELIMITER), StringSplitOptions.RemoveEmptyEntries) - -def DMStringToList(strList): - return strList.split(DMLISTDELIMITER) - -def IsList(value): - return isinstance(value, list) or isinstance(value, Array[str]) - -#all of the below will throw errors if the conversion is not possible -#this behaviour is intended and should be caught in the calling function -#which should report errors at runtime or in the log - -def StringToBool(strValue): - return bool.Parse(strValue) - -def IsBool(value): - return isinstance(value, bool) - -def StringToYesNo(strValue): - ynReturn = None - if strValue == 'Unknown' or strValue == '': - ynReturn = YesNo.Unknown - elif strValue.lower() == 'yes': - ynReturn = YesNo.Yes - elif strValue.lower() == 'no': - ynReturn = YesNo.No - - if ynReturn == None: - raise dmConversionError(strValue, 'ComicRack.Engine.YesNo') - return ynReturn - -def IsYesNo(value): - return isinstance(value, YesNo) - -def StringToMangaYesNo(strValue): - ynReturn = None - if strValue.lower() == 'yes': - ynReturn = MangaYesNo.Yes - elif strValue.lower() == 'no': - ynReturn = MangaYesNo.No - elif strValue.lower() == 'yesandrighttoleft': - ynReturn = MangaYesNo.YesAndRightToLeft - - if ynReturn == None: - raise dmConversionError(strValue, 'ComicRack.Engine.MangaYesNo') - - return ynReturn - -def IsMangaYesNo(value): - return isinstance(value, MangaYesNo) - - -def ToString(obj): - strReturn = '' - if isinstance(obj, YesNo): - if obj == YesNo.Unknown: - strReturn = '' - else: - strReturn = obj.ToString() - elif isinstance(obj, MangaYesNo): - if obj == MangaYesNo.Unknown: - strReturn = '' - else: - strReturn = obj.ToString() - pass - elif isinstance(obj, System.DateTime): - strReturn = obj.ToString(DATEFORMAT) - else: - strReturn = obj.ToString() - - return strReturn - -#############end conversion utilities############### - -#######Field And Modifier helpers############## -def ValidModifiers(strKey, strRuleOrAction): - strListReturn = [] - if strRuleOrAction.lower() == 'rule': - strListReturn = ValidKeyModifiers(strKey) - elif strRuleOrAction.lower() == 'action': - strListReturn = ValidValModifiers(strKey) - return strListReturn - -def ValidKeyModifiers(strKey): - strListReturn = [] - if KeyFieldType(strKey) == 'STRING': - strListReturn = ALLOWEDKEYMODIFIERSSTRING - elif KeyFieldType(strKey) == 'LIST': - strListReturn = ALLOWEDKEYMODIFIERSLIST - elif KeyFieldType(strKey) == 'DATETIME': - strListReturn = ALLOWEDKEYMODIFIERSDATETIME - elif KeyFieldType(strKey) == 'BOOL': - strListReturn = ALLOWEDKEYMODIFIERSBOOL - elif KeyFieldType(strKey) == 'YESNO': - strListReturn = ALLOWEDKEYMODIFIERSYESNO - elif KeyFieldType(strKey) == 'NUMERIC': - strListReturn = ALLOWEDKEYMODIFIERSNUMERIC - elif KeyFieldType(strKey) == 'PSUEDONUMERIC': - strListReturn = ALLOWEDKEYMODIFIERSNUMERIC - elif KeyFieldType(strKey) == 'LANGUAGEISO': - strListReturn = ALLOWEDKEYMODIFIERSLANGUAGEISO - return strListReturn - -def ValidValModifiers(strKey): - strListReturn = [] - if KeyFieldType(strKey) == 'STRING': - strListReturn = ALLOWEDVALMODIFIERSSTRING - elif KeyFieldType(strKey) == 'LIST': - strListReturn = ALLOWEDVALMODIFIERSLIST - elif KeyFieldType(strKey) == 'DATETIME': - strListReturn = ALLOWEDVALMODIFIERSDATETIME - elif KeyFieldType(strKey) == 'BOOL': - strListReturn = ALLOWEDVALMODIFIERSBOOL - elif KeyFieldType(strKey) == 'YESNO': - strListReturn = ALLOWEDVALMODIFIERSYESNO - elif KeyFieldType(strKey) == 'NUMERIC': - strListReturn = ALLOWEDVALMODIFIERSNUMERIC - elif KeyFieldType(strKey) == 'PSUEDONUMERIC': - strListReturn = ALLOWEDVALMODIFIERSNUMERIC - elif KeyFieldType(strKey) == 'LANGUAGEISO': - strListReturn = ALLOWEDVALMODIFIERSLANGUAGEISO - if strKey in REGEXVARREPLACEKEYS: - strListReturn.append('RegExVarReplace') - strListReturn.append('RegExVarAppend') - return strListReturn - -def KeyFieldType(strKey): - strReturn = 'UNKNOWN' - - if strKey in FIELDSSTRING: - strReturn = 'STRING' - elif strKey in FIELDSLIST: - strReturn = 'LIST' - elif strKey in FIELDSDATETIME: - strReturn = 'DATETIME' - elif strKey in FIELDSBOOL: - strReturn = 'BOOL' - elif strKey in FIELDSYESNO: - strReturn = 'YESNO' - elif strKey in FIELDSMANGAYESNO: - strReturn = 'MANGAYESNO' - elif strKey in FILEDSNUMERIC: - strReturn = 'NUMERIC' - elif strKey in FIELDSPSUEDONUMERIC: - strReturn = 'PSUEDONUMERIC' - elif strKey in FIELDSLANGUAGEISO: - strReturn = 'LANGUAGEISO' - return strReturn - -def GetAvailableKeys(strRuleOrAction): - strListReturn = [] - if strRuleOrAction.lower() == 'rule': - strListReturn.extend(ALLOWEDKEYS) - elif strRuleOrAction == 'action': - strListReturn.extend(ALLOWEDVALS) - strListReturn.extend(REGEXVARREPLACEKEYS) - return strListReturn - -def GetAppendString(strKey): - if strKey in FIELDSMULTILINE: - return "\r\n" - else: - return ", " - - pass - -def GetValueType(strFieldName): - strReturn = unknown - #String - if strFieldName in FIELDSSTRING or strFieldName in FIELDSCUSTOM: - strReturn = 'string' - elif strFieldName in FIELDSNUMERIC: - strReturn = 'numeric' - elif strFieldName in FIELDSDATETIME: - strReturn = 'datetime' - elif strFieldName in FIELDSPSUEDONUMERIC: - strReturn = 'psuedonumeric' - elif strFieldName in FIELDSBOOL: - strReturn = 'bool' - elif strFieldName in FIELDSLIST: - strReturn = 'list' - elif strFieldName in FILEDSLANGUAGEISO: - strReturn = 'languageiso' - elif strFieldName in FIELDSYESNO: - strReturn = 'yesno' - elif strFieldName in FIELDSMANGAYESNO: - strReturn = 'mangayesno' - return strReturn - -def ComicVineFields(): - return ['Series','Volume','Number','Title','Published','ReleasedTime','AlternateSeries','Publisher','Imprint','Writer','Penciller','Colorist','Inker','Letterer','CoverArtist','Editor','Summary','Characters'] - -#######Field And Modifier helpers############## - -def WriteStartTime(): - WriteKey(USERINI, 'LastProcessStart', System.DateTime.Now.ToString('yyyy/MM/dd hh:mm:ss')) - -def WriteEndTime(): - WriteKey(USERINI, 'LastProcessEnd', System.DateTime.Now.ToString('yyyy/MM/dd hh:mm:ss')) - -def WriteDurationtime(strDuration): - WriteKey(USERINI, 'LastProcessDuration', strDuration) - -#################### Book Helpers ##################### -def CompareValues(book, cmpDict): - """Compares Values of book to a dictionary of values to see if any values have changed - - Attributes: - book -- the comicbook object holding current values after process has run - cmpDict -- The Dictionary of values that before the process - - - """ - strReturn = '' - - touchedFields = 0 - - for field in cmpDict: - bookValue = None - if field in ALLOWEDVALS: - bookValue = getattr(book, field) - else: - try: - bookValue = book.GetCustomValue(field) - except Exception as er: - bookValue = '' - - - if bookValue != cmpDict[field]: - touchedFields = touchedFields + 1 - - extrastring = '' - if not field in ALLOWEDVALS: - extrastring = 'Custom ' - - strReturn = strReturn + ' ' + extrastring + 'Field: ' + field - strReturn = strReturn + ' Previous Value: ' + cmpDict[field] + System.Environment.NewLine - strReturn = strReturn + ' New Value: ' + bookValue.ToString() + System.Environment.NewLine - return strReturn - -def CreateBookDict(book): - dictReturn = dict() - for item in ALLOWEDVALS: - if item != 'Custom': - dictReturn[item] = getattr(book, item) - else: - customs = book.GetCustomValues() - for field in customs: - dictReturn[field.Key] = field.Value - pass - pass - return dictReturn - -def AppendReport(strInitialReport, strExtendReport): - strReturn = '' - if strInitialReport == None or strInitialReport == '': - strReturn = strExtendReport - else: - strReturn = strInitialReport + System.Environment.NewLine + strExtendReport - return strReturn - -def GetTouchCount(book, tmpDict): - touchedFields = 0 - - for field in tmpDict: - bookValue = None - if field in ALLOWEDVALS: - bookValue = getattr(book, field) - else: - try: - bookValue = book.GetCustomValue(field) - except Exception as er: - bookValue = '' - - - if bookValue != tmpDict[field]: - touchedFields = touchedFields + 1 - - return touchedFields - -def IsCustomField(strFieldName): - bCustom = True - - - - return bCustom - -################ Errors ################ - -class dmException(Exception): - @property - def Message(self): - return self.msg - - def __init__(self, strMessage): - self.msg = strMessage - -class dmConversionError(dmException): - - def __init__(self, value, type): - self.value = value - self.type = type - self.msg = 'Could not convert \'' + self.value + '\' to type \'' + self.type + '\'.' - pass - -def GetStringAsList(strList): - return strList.Split(CRLISTDELIMITER) - -class dmNodeCompileException(dmException): - def __init__(self, strMessage, dmNodeParent): - dmException.__init__(self, strMessage) - self.Parent = dmNodeParent - -class dmGroupCompileException(dmNodeCompileException): - def __init__(strMessage, dmContainerParent): - dmNodeCompileException.__init__(self, strMessage ,dmNodeParent) - -class dmCollectionCompileError(dmNodeCompileException): - def __init__(self, strMessage, dmNodeParent): +# some variables for global use +import clr +import System +from System.IO import Path, FileInfo +import iniReadWrite +from System import Array +from System import StringSplitOptions +from iniReadWrite import * +from System.Collections.Generic import Dictionary +#clr.AddReference("ComicRack.Engine") +from cYo.Projects.ComicRack.Engine import MangaYesNo, YesNo + + +############Set Paths############## +FOLDER = FileInfo(__file__).DirectoryName + Path.DirectorySeparatorChar.ToString() +IMGFOLDER = FOLDER + 'images' + Path.DirectorySeparatorChar.ToString() +DATFILE = Path.Combine(FOLDER, 'dataMan.dat') #can load 1.24 text files or 2.3.1 xml files saves as xml +SAMPLEFILE = Path.Combine(FOLDER, 'dataManSample.dat') +INIFILE = Path.Combine(FOLDER, 'dataMan.ini') +USERINI = Path.Combine(FOLDER, 'user.ini') +BAKFILE = Path.Combine(FOLDER, 'dataMan.bak') +ERRFILE = Path.Combine(FOLDER, 'dataMan.err') +TMPFILE = Path.Combine(FOLDER, 'dataMan.tmp') +LOGFILE = Path.Combine(FOLDER, 'dataMan.log') +CHKFILE = Path.Combine(FOLDER, 'dataMan.chk') # will be created once the configuration is saved +GUIEXE = Path.Combine(FOLDER, 'crdmgui.exe') + +##############End Set Paths############## + +################Set Constant variables############## + +CRLISTDELIMITER = ', ' + +GROUPHEADER = '#@ GROUP ' +RULESETHEADER = '#@ NAME ' +GROUPENDER = '#@ END_GROUP' + +ENDER = '#@ END_RULES' +AUTHORHEADER = '#@ AUTHOR' +NOTESHEADER = '#@ NOTES' + +########################### Images ############################# + +ICON_SMALL = Path.Combine(IMGFOLDER, 'dataMan16.ico') +ICON = Path.Combine(IMGFOLDER, 'dataMan.ico') +IMAGE = Path.Combine(IMGFOLDER, 'dataMan.png') +IMAGESEARCH = Path.Combine(IMGFOLDER, 'search.png') +IMAGEADD = Path.Combine(IMGFOLDER, 'yes.png') +IMAGEAPPLY = Path.Combine(IMGFOLDER, 'Apply.png') +IMAGETRASH = Path.Combine(IMGFOLDER, 'Trash.png') +IMAGEDELETE_SMALL = Path.Combine(IMGFOLDER, 'erase.png') +IMAGEDOWN = Path.Combine(IMGFOLDER, 'down.png') +IMAGELIGHTNING = Path.Combine(IMGFOLDER, 'lightning.png') +IMAGETEXT = Path.Combine(IMGFOLDER, 'text.png') +DONATE = 'https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=UQ7JZY366R85S' +WIKI = 'http://code.google.com/p/cr-data-manager/' +MANUAL = 'http://code.google.com/p/cr-data-manager/downloads/list' + +COMPARE_CASE_SENSITIVE = ReadKeyAsBool(INIFILE, 'CaseSensitive') + + +#############End set constant variables################## + +######################Read From dataman.ini############################### +VERSION = System.Version(ReadKey(INIFILE,'Version')) +DMLISTDELIMITER = ReadKey(INIFILE, 'ListDelimiter') +DATEFORMAT = ReadKey(INIFILE, 'DateTimeFormat') + +####FIELDTYPES AND ALLOWED MODIFIERS######### +ALLOWEDKEYS = ReadKeyAsStringList(INIFILE, 'allowedKeys') +ALLOWEDVALS = ReadKeyAsStringList(INIFILE, 'allowedVals') +READONLYKEYS = ReadKeyAsStringList(INIFILE, 'ReadOnlyKeys') + +ALLOWEDKEYMODIFIERS = ReadKeyAsStringList(INIFILE, 'allowedKeyModifiers') +ALLOWEDVALMODIFIERS = ReadKeyAsStringList(INIFILE, 'allowedValModifiers') + +FIELDSSTRING = ReadKeyAsStringList(INIFILE, 'stringKeys') +ALLOWEDKEYMODIFIERSSTRING = ReadKeyAsStringList(INIFILE, 'allowedKeyModifiersString') +ALLOWEDVALMODIFIERSSTRING = ReadKeyAsStringList(INIFILE, 'allowedValModifiersString') + +FIELDSLIST = ReadKeyAsStringList(INIFILE, 'multiValueKeys') +ALLOWEDKEYMODIFIERSLIST = ReadKeyAsStringList(INIFILE, 'allowedKeyModifiersMulti') +ALLOWEDVALMODIFIERSLIST = ReadKeyAsStringList(INIFILE, 'allowedValModifiersMulti') + +FIELDSDATETIME = ReadKeyAsStringList(INIFILE, 'dateTimeKeys') +ALLOWEDKEYMODIFIERSDATETIME = ReadKeyAsStringList(INIFILE, 'allowedKeyModifierDateTime') +ALLOWEDVALMODIFIERSDATETIME = ReadKeyAsStringList(INIFILE, 'allowedValModifierDateTime') + +FIELDSLANGUAGEISO = ReadKeyAsStringList(INIFILE, 'languageISOKeys') +ALLOWEDKEYMODIFIERSLANGUAGEISO = ReadKeyAsStringList(INIFILE, 'allowedKeyModifierLanguageISO') +ALLOWEDVALMODIFIERSLANGUAGEISO = ReadKeyAsStringList(INIFILE, 'allowedValModifierLanguageISO') + +FIELDSMANGAYESNO = ReadKeyAsStringList(INIFILE, 'mangaYesNoKeys') +ALLOWEDKEYMODIFIERSMANGAYESNO = ReadKeyAsStringList(INIFILE, 'allowedKeyModifierMangaYesNo') +ALLOWEDVALMODIFIERSMANGAYESNO = ReadKeyAsStringList(INIFILE, 'allowedValModifierMangaYesNo') + +FIELDSYESNO = ReadKeyAsStringList(INIFILE, 'yesNoKeys') +ALLOWEDKEYMODIFIERSYESNO = ReadKeyAsStringList(INIFILE, 'allowedKeyModifierYesNo') +ALLOWEDVALMODIFIERSYESNO = ReadKeyAsStringList(INIFILE, 'allowedValModifierYesNo') + +FIELDSBOOL = ReadKeyAsStringList(INIFILE, 'boolKeys') +ALLOWEDKEYMODIFIERSBOOL = ReadKeyAsStringList(INIFILE, 'allowedKeyModifierBool') +ALLOWEDVALMODIFIERSBOOL = ReadKeyAsStringList(INIFILE, 'allowedValModifierBool') + +ALLOWEDKEYMODIFIERSCUSTOM = ReadKeyAsStringList(INIFILE, 'allowedKeyModifierString') +ALLOWEDVALMODIFIERSCUSTOM = ReadKeyAsStringList(INIFILE, 'allowedValModifierString') + +FIELDSNUMERIC = ReadKeyAsStringList(INIFILE, 'numericalKeys') +FIELDSPSUEDONUMERIC = ReadKeyAsStringList(INIFILE, 'pseudoNumericalKeys') +ALLOWEDKEYMODIFIERSNUMERIC = ReadKeyAsStringList(INIFILE, 'allowedKeyModifiersNumeric') +ALLOWEDVALMODIFIERSNUMERIC = ReadKeyAsStringList(INIFILE, 'allowedValModifiersNumeric') + +REGEXVARREPLACEKEYS = ReadKeyAsStringList(INIFILE, 'regExVarReplaceFields') + +MULTIPARAMMODIFIERS = ReadKeyAsStringList(INIFILE, 'multipleParamModifiers') + +FIELDSMULTILINE = ReadKeyAsStringList(INIFILE, 'multiLineKeys') +####END FIELDTYPES AND ALLOWED MODIFIERS######### +#################End read From dataman.ini############################ + +#####################Read From User.ini####################### +BreakAfterFirstError = ReadKeyAsBool(USERINI, "BreakAfterFirstError") +TraceGeneralMessages = ReadKeyAsBool(USERINI, 'TraceGeneralMessages') +TraceFunctionMessages = ReadKeyAsBool(USERINI, 'TraceFunctionMessages') +SortLists = ReadKeyAsBool(USERINI, 'SortLists') +#############type conversion utilities ######################## + +def StringToDate(strDate): + if strDate == '': + return System.DateTime(1,1,1) + return System.DateTime.Parse(strDate) + +def IsDateTime(value): + return isinstance(value, System.DateTime) + +def StringToInt(strNumber): + if strNumber == '': + return int(-1) + return int(strNumber) + +def IsInt(value): + return isinstance(value, System.Int32) + +def StringToFloat(strFloat): + fValue = float(-1) + fValue = float(strFloat) + return fValue + +def IsFloat(value): + return isinstance(value, float) + +def CRStringToList(strList): + return strList.Split(Array[str](CRLISTDELIMITER), StringSplitOptions.RemoveEmptyEntries) + +def DMStringToList(strList): + return strList.split(DMLISTDELIMITER) + +def IsList(value): + return isinstance(value, list) or isinstance(value, Array[str]) + +#all of the below will throw errors if the conversion is not possible +#this behaviour is intended and should be caught in the calling function +#which should report errors at runtime or in the log + +def StringToBool(strValue): + return bool.Parse(strValue) + +def IsBool(value): + return isinstance(value, bool) + +def StringToYesNo(strValue): + ynReturn = None + if strValue == 'Unknown' or strValue == '': + ynReturn = YesNo.Unknown + elif strValue.lower() == 'yes': + ynReturn = YesNo.Yes + elif strValue.lower() == 'no': + ynReturn = YesNo.No + + if ynReturn == None: + raise dmConversionError(strValue, 'ComicRack.Engine.YesNo') + return ynReturn + +def IsYesNo(value): + return isinstance(value, YesNo) + +def StringToMangaYesNo(strValue): + ynReturn = None + if strValue.lower() == 'yes': + ynReturn = MangaYesNo.Yes + elif strValue.lower() == 'no': + ynReturn = MangaYesNo.No + elif strValue.lower() == 'yesandrighttoleft': + ynReturn = MangaYesNo.YesAndRightToLeft + + if ynReturn == None: + raise dmConversionError(strValue, 'ComicRack.Engine.MangaYesNo') + + return ynReturn + +def IsMangaYesNo(value): + return isinstance(value, MangaYesNo) + + +def ToString(obj): + strReturn = '' + if isinstance(obj, YesNo): + if obj == YesNo.Unknown: + strReturn = '' + else: + strReturn = obj.ToString() + elif isinstance(obj, MangaYesNo): + if obj == MangaYesNo.Unknown: + strReturn = '' + else: + strReturn = obj.ToString() + pass + elif isinstance(obj, System.DateTime): + strReturn = obj.ToString(DATEFORMAT) + else: + strReturn = obj.ToString() + + return strReturn + +#############end conversion utilities############### + +#######Field And Modifier helpers############## +def ValidModifiers(strKey, strRuleOrAction): + strListReturn = [] + if strRuleOrAction.lower() == 'rule': + strListReturn = ValidKeyModifiers(strKey) + elif strRuleOrAction.lower() == 'action': + strListReturn = ValidValModifiers(strKey) + return strListReturn + +def ValidKeyModifiers(strKey): + strListReturn = [] + if KeyFieldType(strKey) == 'STRING': + strListReturn = ALLOWEDKEYMODIFIERSSTRING + elif KeyFieldType(strKey) == 'LIST': + strListReturn = ALLOWEDKEYMODIFIERSLIST + elif KeyFieldType(strKey) == 'DATETIME': + strListReturn = ALLOWEDKEYMODIFIERSDATETIME + elif KeyFieldType(strKey) == 'BOOL': + strListReturn = ALLOWEDKEYMODIFIERSBOOL + elif KeyFieldType(strKey) == 'YESNO': + strListReturn = ALLOWEDKEYMODIFIERSYESNO + elif KeyFieldType(strKey) == 'NUMERIC': + strListReturn = ALLOWEDKEYMODIFIERSNUMERIC + elif KeyFieldType(strKey) == 'PSUEDONUMERIC': + strListReturn = ALLOWEDKEYMODIFIERSNUMERIC + elif KeyFieldType(strKey) == 'LANGUAGEISO': + strListReturn = ALLOWEDKEYMODIFIERSLANGUAGEISO + return strListReturn + +def ValidValModifiers(strKey): + strListReturn = [] + if KeyFieldType(strKey) == 'STRING': + strListReturn = ALLOWEDVALMODIFIERSSTRING + elif KeyFieldType(strKey) == 'LIST': + strListReturn = ALLOWEDVALMODIFIERSLIST + elif KeyFieldType(strKey) == 'DATETIME': + strListReturn = ALLOWEDVALMODIFIERSDATETIME + elif KeyFieldType(strKey) == 'BOOL': + strListReturn = ALLOWEDVALMODIFIERSBOOL + elif KeyFieldType(strKey) == 'YESNO': + strListReturn = ALLOWEDVALMODIFIERSYESNO + elif KeyFieldType(strKey) == 'NUMERIC': + strListReturn = ALLOWEDVALMODIFIERSNUMERIC + elif KeyFieldType(strKey) == 'PSUEDONUMERIC': + strListReturn = ALLOWEDVALMODIFIERSNUMERIC + elif KeyFieldType(strKey) == 'LANGUAGEISO': + strListReturn = ALLOWEDVALMODIFIERSLANGUAGEISO + if strKey in REGEXVARREPLACEKEYS: + strListReturn.append('RegExVarReplace') + strListReturn.append('RegExVarAppend') + return strListReturn + +def KeyFieldType(strKey): + strReturn = 'UNKNOWN' + + if strKey in FIELDSSTRING: + strReturn = 'STRING' + elif strKey in FIELDSLIST: + strReturn = 'LIST' + elif strKey in FIELDSDATETIME: + strReturn = 'DATETIME' + elif strKey in FIELDSBOOL: + strReturn = 'BOOL' + elif strKey in FIELDSYESNO: + strReturn = 'YESNO' + elif strKey in FIELDSMANGAYESNO: + strReturn = 'MANGAYESNO' + elif strKey in FILEDSNUMERIC: + strReturn = 'NUMERIC' + elif strKey in FIELDSPSUEDONUMERIC: + strReturn = 'PSUEDONUMERIC' + elif strKey in FIELDSLANGUAGEISO: + strReturn = 'LANGUAGEISO' + return strReturn + +def GetAvailableKeys(strRuleOrAction): + strListReturn = [] + if strRuleOrAction.lower() == 'rule': + strListReturn.extend(ALLOWEDKEYS) + elif strRuleOrAction == 'action': + strListReturn.extend(ALLOWEDVALS) + strListReturn.extend(REGEXVARREPLACEKEYS) + return strListReturn + +def GetAppendString(strKey): + if strKey in FIELDSMULTILINE: + return "\r\n" + else: + return ", " + + pass + +def GetValueType(strFieldName): + strReturn = unknown + #String + if strFieldName in FIELDSSTRING or strFieldName in FIELDSCUSTOM: + strReturn = 'string' + elif strFieldName in FIELDSNUMERIC: + strReturn = 'numeric' + elif strFieldName in FIELDSDATETIME: + strReturn = 'datetime' + elif strFieldName in FIELDSPSUEDONUMERIC: + strReturn = 'psuedonumeric' + elif strFieldName in FIELDSBOOL: + strReturn = 'bool' + elif strFieldName in FIELDSLIST: + strReturn = 'list' + elif strFieldName in FILEDSLANGUAGEISO: + strReturn = 'languageiso' + elif strFieldName in FIELDSYESNO: + strReturn = 'yesno' + elif strFieldName in FIELDSMANGAYESNO: + strReturn = 'mangayesno' + return strReturn + +def ComicVineFields(): + return ['Series','Volume','Number','Title','Published','ReleasedTime','AlternateSeries','Publisher','Imprint','Writer','Penciller','Colorist','Inker','Letterer','CoverArtist','Editor','Summary','Characters'] + +#######Field And Modifier helpers############## + +def WriteStartTime(): + WriteKey(USERINI, 'LastProcessStart', System.DateTime.Now.ToString('yyyy/MM/dd hh:mm:ss')) + +def WriteEndTime(): + WriteKey(USERINI, 'LastProcessEnd', System.DateTime.Now.ToString('yyyy/MM/dd hh:mm:ss')) + +def WriteDurationtime(strDuration): + WriteKey(USERINI, 'LastProcessDuration', strDuration) + +#################### Book Helpers ##################### +def CompareValues(book, cmpDict): + """Compares Values of book to a dictionary of values to see if any values have changed + + Attributes: + book -- the comicbook object holding current values after process has run + cmpDict -- The Dictionary of values that before the process + + + """ + strReturn = '' + + touchedFields = 0 + + for field in cmpDict: + bookValue = None + if field in ALLOWEDVALS: + bookValue = getattr(book, field) + else: + try: + bookValue = book.GetCustomValue(field) + except Exception as er: + bookValue = '' + + + if bookValue != cmpDict[field]: + touchedFields = touchedFields + 1 + + extrastring = '' + if not field in ALLOWEDVALS: + extrastring = 'Custom ' + + strReturn = strReturn + ' ' + extrastring + 'Field: ' + field + strReturn = strReturn + ' Previous Value: ' + cmpDict[field] + System.Environment.NewLine + strReturn = strReturn + ' New Value: ' + bookValue.ToString() + System.Environment.NewLine + return strReturn + +def CreateBookDict(book): + dictReturn = dict() + for item in ALLOWEDVALS: + if item != 'Custom': + dictReturn[item] = getattr(book, item) + else: + customs = book.GetCustomValues() + for field in customs: + dictReturn[field.Key] = field.Value + pass + pass + return dictReturn + +def AppendReport(strInitialReport, strExtendReport): + strReturn = '' + if strInitialReport == None or strInitialReport == '': + strReturn = strExtendReport + else: + strReturn = strInitialReport + System.Environment.NewLine + strExtendReport + return strReturn + +def GetTouchCount(book, tmpDict): + touchedFields = 0 + + for field in tmpDict: + bookValue = None + if field in ALLOWEDVALS: + bookValue = getattr(book, field) + else: + try: + bookValue = book.GetCustomValue(field) + except Exception as er: + bookValue = '' + + + if bookValue != tmpDict[field]: + touchedFields = touchedFields + 1 + + return touchedFields + +def IsCustomField(strFieldName): + bCustom = True + + + + return bCustom + +################ Errors ################ + +class dmException(Exception): + @property + def Message(self): + return self.msg + + def __init__(self, strMessage): + self.msg = strMessage + +class dmConversionError(dmException): + + def __init__(self, value, type): + self.value = value + self.type = type + self.msg = 'Could not convert \'' + self.value + '\' to type \'' + self.type + '\'.' + pass + +def GetStringAsList(strList): + return strList.Split(CRLISTDELIMITER) + +class dmNodeCompileException(dmException): + def __init__(self, strMessage, dmNodeParent): + dmException.__init__(self, strMessage) + self.Parent = dmNodeParent + +class dmGroupCompileException(dmNodeCompileException): + def __init__(strMessage, dmContainerParent): + dmNodeCompileException.__init__(self, strMessage ,dmNodeParent) + +class dmCollectionCompileError(dmNodeCompileException): + def __init__(self, strMessage, dmNodeParent): dmNodeCompileException.__init__(self, strMessage, dmNodeParent) \ No newline at end of file diff --git a/dmMod.py b/dmMod.py index 23d7b71..989f925 100644 --- a/dmMod.py +++ b/dmMod.py @@ -1,96 +1,96 @@ -import clr -import sys -import System -clr.AddReference('System.Windows.Forms') -clr.AddReference('System.Drawing') - - -import System.Drawing -import System.Windows.Forms -import System.Diagnostics -import dmClasses -import dmGlobals -import iniReadWrite -import runProcess - -from dmClasses import * -from System.Diagnostics import Process -from runProcess import runProcess -# this handles unicode encoding: -bodyname = System.Text.Encoding.Default.BodyName -sys.setdefaultencoding(bodyname) - -def crVersion(): - ''' checks the CR version if it is min. 0.9.164 (for custom values) ''' - minVersion = '0.9.164' # we need CR 0.9.164 minimum (for custom values) - vMin = 0 + 9000 + 164 - myVersion = ComicRack.App.ProductVersion # get the installed CR version number - v = myVersion.split('.') - vMyVersion = (int(v[0]) * 1000000) + (int(v[1]) * 1000) + int(v[2]) - if vMyVersion < vMin: # if actual version is lower than minimum version: return False - MessageBox.Show( - 'You have only CR version %s installed.\nPlease install at least version %s of ComicRack first!' % (myVersion,minVersion), - 'Data Manger for ComicRack %s' % globalvars.VERSION) - return False - return True - -# ============================================================================ -# hook to run the configScript -#@Name Data Manager configuration -#@Key data-manager-mod -#@Hook ConfigScript -# ============================================================================ -def dmRunConfig(): - #read ini info - p = System.Diagnostics.Process() - p.StartInfo.FileName = dmGlobals.GUIEXE - p.Start() - pass - - -# ============================================================================ -# hook to run the main dataManager loop -#@Name Data Manager Mod -#@Image dataMan16.png -#@Key data-manager-mod -#@Hook Books -# ============================================================================ -def dmRunProcess(books): - if File.Exists(dmGlobals.DATFILE): - if len(books) > 0: - collection = dmCollection(dmGlobals.DATFILE) - processor = runProcess(books,collection) - processor.ShowDialog(ComicRack.MainWindow) - processor.Dispose() - pass - elif File.Exists(dmGlobals.OLDDATFILE): - pass - else: - System.Windows.Forms.MessageBox.Show("There is no Ruleset Collection to process.\r\nPlease use configuration to set up your rules", "No Ruleset Defined", System.Windows.Forms.MessageBoxButtons.OK) - - pass - -def dmAutoCreateRules(books): - if not File.Exists(dmGlobals.AUTOCREATEFILE): - if System.Windows.Forms.MessageBox.Show('No Auto create Rule definitions exist\r\nWould you like to manage them now?', 'No definitions exist', System.Windows.Forms.MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.Yes: - dmConfigAutocreateRun(books) - else: - pass - else: - dmAutoCreateQuickDialog(books) - pass - -def dmAutoCreateQuickDialog(books): - if books != None: - - pass - pass - - -def dmConfigAutoCreate(): - books = ComicRack.App.GetLibraryBooks() - pass - -def dmConfigAutocreateRun(books): - +import clr +import sys +import System +clr.AddReference('System.Windows.Forms') +clr.AddReference('System.Drawing') + + +import System.Drawing +import System.Windows.Forms +import System.Diagnostics +import dmClasses +import dmGlobals +import iniReadWrite +import runProcess + +from dmClasses import * +from System.Diagnostics import Process +from runProcess import runProcess +# this handles unicode encoding: +bodyname = System.Text.Encoding.Default.BodyName +sys.setdefaultencoding(bodyname) + +def crVersion(): + ''' checks the CR version if it is min. 0.9.164 (for custom values) ''' + minVersion = '0.9.164' # we need CR 0.9.164 minimum (for custom values) + vMin = 0 + 9000 + 164 + myVersion = ComicRack.App.ProductVersion # get the installed CR version number + v = myVersion.split('.') + vMyVersion = (int(v[0]) * 1000000) + (int(v[1]) * 1000) + int(v[2]) + if vMyVersion < vMin: # if actual version is lower than minimum version: return False + MessageBox.Show( + 'You have only CR version %s installed.\nPlease install at least version %s of ComicRack first!' % (myVersion,minVersion), + 'Data Manger for ComicRack %s' % globalvars.VERSION) + return False + return True + +# ============================================================================ +# hook to run the configScript +#@Name Data Manager configuration +#@Key data-manager-mod +#@Hook ConfigScript +# ============================================================================ +def dmRunConfig(): + #read ini info + p = System.Diagnostics.Process() + p.StartInfo.FileName = dmGlobals.GUIEXE + p.Start() + pass + + +# ============================================================================ +# hook to run the main dataManager loop +#@Name Data Manager Mod +#@Image dataMan16.png +#@Key data-manager-mod +#@Hook Books +# ============================================================================ +def dmRunProcess(books): + if File.Exists(dmGlobals.DATFILE): + if len(books) > 0: + collection = dmCollection(dmGlobals.DATFILE) + processor = runProcess(books,collection) + processor.ShowDialog(ComicRack.MainWindow) + processor.Dispose() + pass + elif File.Exists(dmGlobals.OLDDATFILE): + pass + else: + System.Windows.Forms.MessageBox.Show("There is no Ruleset Collection to process.\r\nPlease use configuration to set up your rules", "No Ruleset Defined", System.Windows.Forms.MessageBoxButtons.OK) + + pass + +def dmAutoCreateRules(books): + if not File.Exists(dmGlobals.AUTOCREATEFILE): + if System.Windows.Forms.MessageBox.Show('No Auto create Rule definitions exist\r\nWould you like to manage them now?', 'No definitions exist', System.Windows.Forms.MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.Yes: + dmConfigAutocreateRun(books) + else: + pass + else: + dmAutoCreateQuickDialog(books) + pass + +def dmAutoCreateQuickDialog(books): + if books != None: + + pass + pass + + +def dmConfigAutoCreate(): + books = ComicRack.App.GetLibraryBooks() + pass + +def dmConfigAutocreateRun(books): + pass \ No newline at end of file diff --git a/iniReadWrite.py b/iniReadWrite.py index aeef7c7..039f1ac 100644 --- a/iniReadWrite.py +++ b/iniReadWrite.py @@ -1,46 +1,46 @@ -import clr -import System -import System.IO - -from System.IO import File, Path, Directory - -def ReadKey(iniFilePath, strKey): - dictKeys = LoadFile(iniFilePath) - strReturn = '' - if dictKeys.has_key(strKey): - strReturn = dictKeys[strKey] - return strReturn - -def ReadKeyAsStringList(iniFilePath, strKey): - dictKeys = LoadFile(iniFilePath) - ListReturn = [] - if dictKeys.has_key(strKey): - ListReturn = dictKeys[strKey].split(',') - return ListReturn - -def ReadKeyAsBool(iniFilePath, strKey): - dictKeys = LoadFile(iniFilePath) - bReturn = False - try: - bReturn = bool.Parse(dictKeys[strKey]) - except: - pass - return bReturn - -def WriteKey(iniFilePath, strKey, strValue): - dictKeys = LoadFile(iniFilePath) - dictKeys[strKey] = strValue - strFile = "" - for item in dictKeys: - strFile += item + ' = ' + dictKeys[item] + System.Environment.NewLine - File.WriteAllText(iniFilePath, strFile) - pass - -def LoadFile(iniFilePath): - dictKeys = dict() - if File.Exists(iniFilePath): - KeyLines = File.ReadAllLines(iniFilePath) - for line in KeyLines: - if not line.startswith(';') and not line.strip() == '': - dictKeys.Add(line.split(' = ')[0].strip(),line.split('=')[1].strip()) +import clr +import System +import System.IO + +from System.IO import File, Path, Directory + +def ReadKey(iniFilePath, strKey): + dictKeys = LoadFile(iniFilePath) + strReturn = '' + if dictKeys.has_key(strKey): + strReturn = dictKeys[strKey] + return strReturn + +def ReadKeyAsStringList(iniFilePath, strKey): + dictKeys = LoadFile(iniFilePath) + ListReturn = [] + if dictKeys.has_key(strKey): + ListReturn = dictKeys[strKey].split(',') + return ListReturn + +def ReadKeyAsBool(iniFilePath, strKey): + dictKeys = LoadFile(iniFilePath) + bReturn = False + try: + bReturn = bool.Parse(dictKeys[strKey]) + except: + pass + return bReturn + +def WriteKey(iniFilePath, strKey, strValue): + dictKeys = LoadFile(iniFilePath) + dictKeys[strKey] = strValue + strFile = "" + for item in dictKeys: + strFile += item + ' = ' + dictKeys[item] + System.Environment.NewLine + File.WriteAllText(iniFilePath, strFile) + pass + +def LoadFile(iniFilePath): + dictKeys = dict() + if File.Exists(iniFilePath): + KeyLines = File.ReadAllLines(iniFilePath) + for line in KeyLines: + if not line.startswith(';') and not line.strip() == '': + dictKeys.Add(line.split(' = ')[0].strip(),line.split('=')[1].strip()) return dictKeys \ No newline at end of file diff --git a/pyevent.py b/pyevent.py index 7ab4ace..01fdfb8 100644 --- a/pyevent.py +++ b/pyevent.py @@ -1,84 +1,84 @@ -##################################################################################### -# -# Copyright (c) Microsoft Corporation. All rights reserved. -# -# This source code is subject to terms and conditions of the Apache License, Version 2.0. A -# copy of the license can be found in the License.html file at the root of this distribution. If -# you cannot locate the Apache License, Version 2.0, please send an email to -# ironpy@microsoft.com. By using this source code in any fashion, you are agreeing to be bound -# by the terms of the Apache License, Version 2.0. -# -# You must not remove this notice, or any other, from this software. -# -# -##################################################################################### - -class event(object): - """Provides CLR event-like functionality for Python. This is a public - event helper that allows adding and removing handlers.""" - __slots__ = ['handlers'] - - def __init__(self): - self.handlers = [] - - def __iadd__(self, other): - if isinstance(other, event): - self.handlers.extend(other.handlers) - elif isinstance(other, event_caller): - self.handlers.extend(other.event.handlers) - else: - if not callable(other): - raise TypeError, "cannot assign to event unless value is callable" - self.handlers.append(other) - return self - - def __isub__(self, other): - if isinstance(other, event): - newEv = [] - for x in self.handlers: - if not other.handlers.contains(x): - newEv.append(x) - self.handlers = newEv - elif isinstance(other, event_caller): - newEv = [] - for x in self.handlers: - if not other.event.handlers.contains(x): - newEv.append(x) - self.handlers = newEv - else: - if other in self.handlers: - self.handlers.remove(other) - return self - - def make_caller(self): - return event_caller(self) - -class event_caller(object): - """Provides CLR event-like functionality for Python. This is the - protected event caller that allows the owner to raise the event""" - __slots__ = ['event'] - - def __init__(self, event): - self.event = event - - def __call__(self, *args): - for ev in self.event.handlers: - ev(*args) - - def __set__(self, val): - raise ValueError, "cannot assign to an event, can only add or remove handlers" - - def __delete__(self, val): - raise ValueError, "cannot delete an event, can only add or remove handlers" - - def __get__(self, instance, owner): - return self - -def make_event(): - """Creates an event object tuple. The first value in the tuple can be - exposed to allow external code to hook and unhook from the event. The - second value can be used to raise the event and can be stored in a - private variable.""" - res = event() - - return (res, res.make_caller()) +##################################################################################### +# +# Copyright (c) Microsoft Corporation. All rights reserved. +# +# This source code is subject to terms and conditions of the Apache License, Version 2.0. A +# copy of the license can be found in the License.html file at the root of this distribution. If +# you cannot locate the Apache License, Version 2.0, please send an email to +# ironpy@microsoft.com. By using this source code in any fashion, you are agreeing to be bound +# by the terms of the Apache License, Version 2.0. +# +# You must not remove this notice, or any other, from this software. +# +# +##################################################################################### + +class event(object): + """Provides CLR event-like functionality for Python. This is a public + event helper that allows adding and removing handlers.""" + __slots__ = ['handlers'] + + def __init__(self): + self.handlers = [] + + def __iadd__(self, other): + if isinstance(other, event): + self.handlers.extend(other.handlers) + elif isinstance(other, event_caller): + self.handlers.extend(other.event.handlers) + else: + if not callable(other): + raise TypeError, "cannot assign to event unless value is callable" + self.handlers.append(other) + return self + + def __isub__(self, other): + if isinstance(other, event): + newEv = [] + for x in self.handlers: + if not other.handlers.contains(x): + newEv.append(x) + self.handlers = newEv + elif isinstance(other, event_caller): + newEv = [] + for x in self.handlers: + if not other.event.handlers.contains(x): + newEv.append(x) + self.handlers = newEv + else: + if other in self.handlers: + self.handlers.remove(other) + return self + + def make_caller(self): + return event_caller(self) + +class event_caller(object): + """Provides CLR event-like functionality for Python. This is the + protected event caller that allows the owner to raise the event""" + __slots__ = ['event'] + + def __init__(self, event): + self.event = event + + def __call__(self, *args): + for ev in self.event.handlers: + ev(*args) + + def __set__(self, val): + raise ValueError, "cannot assign to an event, can only add or remove handlers" + + def __delete__(self, val): + raise ValueError, "cannot delete an event, can only add or remove handlers" + + def __get__(self, instance, owner): + return self + +def make_event(): + """Creates an event object tuple. The first value in the tuple can be + exposed to allow external code to hook and unhook from the event. The + second value can be used to raise the event and can be stored in a + private variable.""" + res = event() + + return (res, res.make_caller()) diff --git a/runProcess.py b/runProcess.py index dd37129..69a4461 100644 --- a/runProcess.py +++ b/runProcess.py @@ -1,216 +1,216 @@ -import System -import System.Drawing -import System.Windows.Forms -import dmClasses - -from System.Drawing import * -from System.Windows.Forms import * -from dmClasses import * - -class runProcess(Form): - def __init__(self, books, collection): - self.InitializeComponent() - self.Books = books - self.Collection = collection - pass - - def InitializeComponent(self): - self._progressBar1 = System.Windows.Forms.ProgressBar() - self._btnCancel = System.Windows.Forms.Button() - self._bgwProcess = System.ComponentModel.BackgroundWorker() - self._label1 = System.Windows.Forms.Label() - self._label2 = System.Windows.Forms.Label() - self._textBox1 = System.Windows.Forms.TextBox() - self._splitContainer1 = System.Windows.Forms.SplitContainer() - self._splitContainer1.BeginInit() - self._splitContainer1.Panel1.SuspendLayout() - self._splitContainer1.Panel2.SuspendLayout() - self._splitContainer1.SuspendLayout() - self.SuspendLayout() - # - # progressBar1 - # - self._progressBar1.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right - self._progressBar1.Location = System.Drawing.Point(4, 33) - self._progressBar1.Name = "progressBar1" - self._progressBar1.Size = System.Drawing.Size(515, 30) - self._progressBar1.TabIndex = 0 - # - # btnCancel - # - self._btnCancel.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right - self._btnCancel.Location = System.Drawing.Point(414, 289) - self._btnCancel.Name = "btnCancel" - self._btnCancel.Size = System.Drawing.Size(105, 22) - self._btnCancel.TabIndex = 1 - self._btnCancel.Text = "Cancel" - self._btnCancel.UseVisualStyleBackColor = True - self._btnCancel.Click += self.BtnCancelClick - # - # bgwProcess - # - self._bgwProcess.WorkerReportsProgress = True - self._bgwProcess.WorkerSupportsCancellation = True - self._bgwProcess.DoWork += self.BgwProcessDoWork - self._bgwProcess.ProgressChanged += self.BgwProcessProgressChanged - self._bgwProcess.RunWorkerCompleted += self.BgwProcessRunWorkerCompleted - # - # label1 - # - self._label1.Location = System.Drawing.Point(4, 5) - self._label1.Name = "label1" - self._label1.Size = System.Drawing.Size(252, 23) - self._label1.TabIndex = 2 - self._label1.Text = "Processing book 0 of 0" - self._label1.TextAlign = System.Drawing.ContentAlignment.MiddleLeft - self._label1.UseMnemonic = False - # - # label2 - # - self._label2.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right - self._label2.Location = System.Drawing.Point(264, 5) - self._label2.Name = "label2" - self._label2.Size = System.Drawing.Size(252, 23) - self._label2.TabIndex = 2 - self._label2.Text = "Processing book 0 of 0" - self._label2.TextAlign = System.Drawing.ContentAlignment.MiddleRight - self._label2.UseMnemonic = False - # - # textBox1 - # - self._textBox1.BackColor = System.Drawing.SystemColors.Window - self._textBox1.Dock = System.Windows.Forms.DockStyle.Fill - self._textBox1.Location = System.Drawing.Point(0, 0) - self._textBox1.Multiline = True - self._textBox1.Name = "textBox1" - self._textBox1.ReadOnly = True - self._textBox1.ScrollBars = System.Windows.Forms.ScrollBars.Both - self._textBox1.Size = System.Drawing.Size(526, 211) - self._textBox1.TabIndex = 3 - self._textBox1.WordWrap = False - # - # splitContainer1 - # - self._splitContainer1.Dock = System.Windows.Forms.DockStyle.Top - self._splitContainer1.Location = System.Drawing.Point(0, 0) - self._splitContainer1.Name = "splitContainer1" - self._splitContainer1.Orientation = System.Windows.Forms.Orientation.Horizontal - # - # splitContainer1.Panel1 - # - self._splitContainer1.Panel1.Controls.Add(self._label2) - self._splitContainer1.Panel1.Controls.Add(self._progressBar1) - self._splitContainer1.Panel1.Controls.Add(self._label1) - # - # splitContainer1.Panel2 - # - self._splitContainer1.Panel2.Controls.Add(self._textBox1) - self._splitContainer1.Size = System.Drawing.Size(526, 283) - self._splitContainer1.SplitterDistance = 68 - self._splitContainer1.TabIndex = 4 - # - # runProcess - # - self.ClientSize = System.Drawing.Size(526, 318) - self.Controls.Add(self._splitContainer1) - self.Controls.Add(self._btnCancel) - self.Name = "runProcess" - self.Text = "runProcess" - self.Shown += self.RunProcessShown - self._splitContainer1.Panel1.ResumeLayout(False) - self._splitContainer1.Panel2.ResumeLayout(False) - self._splitContainer1.Panel2.PerformLayout() - self._splitContainer1.EndInit() - self._splitContainer1.ResumeLayout(False) - self.ResumeLayout(False) - - def BgwProcessDoWork(self, sender, e): - collection = e.Argument[0] - books = e.Argument[1] - - count = 0 - bookTouchCount = 0 - fieldTouchCount = 0 - - userVariables = Dictionary[str,str]() - - strReport = '' - - if System.IO.File.Exists(dmGlobals.LOGFILE): - System.IO.File.Delete(dmGlobals.LOGFILE) - - dtStart = System.DateTime.Now - dmGlobals.WriteStartTime() - while count < len(books): - tmpDic = dmGlobals.CreateBookDict(books[count]) - if not self._bgwProcess.CancellationPending: - self._bgwProcess.ReportProgress((100 / len(books)) * count + 1, [count, books[count]]) - if dmGlobals.TraceGeneralMessages: print 'Processing Ruleset Collection' - bookReport = collection.ProcessBook(books[count], self._bgwProcess) - if bookReport != '': - strReport = dmGlobals.AppendReport(strReport, bookReport) - bookTouchCount = bookTouchCount + 1 - fieldTouchCount = fieldTouchCount + dmGlobals.GetTouchCount(books[count], tmpDic) - count = count + 1 - - - #add touch count to log - strReport = strReport + System.Environment.NewLine + System.Environment.NewLine + bookTouchCount.ToString() + ' Books were modified. ' + fieldTouchCount.ToString() + ' Values were changed' - self._bgwProcess.ReportProgress(100, [count, strReport]) - - #write out report - if strReport!= '': - System.IO.File.WriteAllText(dmGlobals.LOGFILE, strReport) - - dmGlobals.WriteEndTime() - duration = System.DateTime.Now - dtStart - strDuration = duration.ToString('hh\:mm\:ss\.ffff') - dmGlobals.WriteDurationtime(strDuration) - - pass - - def BgwProcessProgressChanged(self, sender, e): - progress = e.ProgressPercentage - self.SetProgress(progress, e.UserState) - pass - - def SetProgress(self, progress, userState): - if self.InvokeRequired: - self.Invoke(self.SetProgress, [progress, userState]) - return - - self._progressBar1.Value = progress - if isinstance(userState, list): - if isinstance(userState[1], str): - self._textBox1.Text = userState[1] - else: - self._label2.Text = userState[1].CaptionWithoutTitle - - count = userState[0] - booklen = len(self.Books) - booklen = booklen.ToString() - bookcount = count.ToString() - - self._progressBar1.Value = progress - self._label1.Text = 'Processing ' + bookcount + ' of '+ booklen +' books' - pass - - def BtnCancelClick(self,sender, e): - if self._bgwProcess.IsBusy: - self._bgwProcess.CancelAsync() - else: - self.Close() - - def BgwProcessRunWorkerCompleted(self, sender, e): - self._btnCancel.Text = 'Close' - - def RunProcessShown(self, sender, e): - if len(self.Books) > 0: - self._btnCancel.Text = 'Cancel' - if self._btnCancel.Click == None: - self._btnCancel.Click += self.BtnCancelClick - self._bgwProcess.RunWorkerAsync([self.Collection, self.Books]) - else: - strMessage = 'The following issues need to be attended to\r\n before you can run Data Manager:' - strMessage = strMessage + '\r\n no books are selected' +import System +import System.Drawing +import System.Windows.Forms +import dmClasses + +from System.Drawing import * +from System.Windows.Forms import * +from dmClasses import * + +class runProcess(Form): + def __init__(self, books, collection): + self.InitializeComponent() + self.Books = books + self.Collection = collection + pass + + def InitializeComponent(self): + self._progressBar1 = System.Windows.Forms.ProgressBar() + self._btnCancel = System.Windows.Forms.Button() + self._bgwProcess = System.ComponentModel.BackgroundWorker() + self._label1 = System.Windows.Forms.Label() + self._label2 = System.Windows.Forms.Label() + self._textBox1 = System.Windows.Forms.TextBox() + self._splitContainer1 = System.Windows.Forms.SplitContainer() + self._splitContainer1.BeginInit() + self._splitContainer1.Panel1.SuspendLayout() + self._splitContainer1.Panel2.SuspendLayout() + self._splitContainer1.SuspendLayout() + self.SuspendLayout() + # + # progressBar1 + # + self._progressBar1.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right + self._progressBar1.Location = System.Drawing.Point(4, 33) + self._progressBar1.Name = "progressBar1" + self._progressBar1.Size = System.Drawing.Size(515, 30) + self._progressBar1.TabIndex = 0 + # + # btnCancel + # + self._btnCancel.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right + self._btnCancel.Location = System.Drawing.Point(414, 289) + self._btnCancel.Name = "btnCancel" + self._btnCancel.Size = System.Drawing.Size(105, 22) + self._btnCancel.TabIndex = 1 + self._btnCancel.Text = "Cancel" + self._btnCancel.UseVisualStyleBackColor = True + self._btnCancel.Click += self.BtnCancelClick + # + # bgwProcess + # + self._bgwProcess.WorkerReportsProgress = True + self._bgwProcess.WorkerSupportsCancellation = True + self._bgwProcess.DoWork += self.BgwProcessDoWork + self._bgwProcess.ProgressChanged += self.BgwProcessProgressChanged + self._bgwProcess.RunWorkerCompleted += self.BgwProcessRunWorkerCompleted + # + # label1 + # + self._label1.Location = System.Drawing.Point(4, 5) + self._label1.Name = "label1" + self._label1.Size = System.Drawing.Size(252, 23) + self._label1.TabIndex = 2 + self._label1.Text = "Processing book 0 of 0" + self._label1.TextAlign = System.Drawing.ContentAlignment.MiddleLeft + self._label1.UseMnemonic = False + # + # label2 + # + self._label2.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right + self._label2.Location = System.Drawing.Point(264, 5) + self._label2.Name = "label2" + self._label2.Size = System.Drawing.Size(252, 23) + self._label2.TabIndex = 2 + self._label2.Text = "Processing book 0 of 0" + self._label2.TextAlign = System.Drawing.ContentAlignment.MiddleRight + self._label2.UseMnemonic = False + # + # textBox1 + # + self._textBox1.BackColor = System.Drawing.SystemColors.Window + self._textBox1.Dock = System.Windows.Forms.DockStyle.Fill + self._textBox1.Location = System.Drawing.Point(0, 0) + self._textBox1.Multiline = True + self._textBox1.Name = "textBox1" + self._textBox1.ReadOnly = True + self._textBox1.ScrollBars = System.Windows.Forms.ScrollBars.Both + self._textBox1.Size = System.Drawing.Size(526, 211) + self._textBox1.TabIndex = 3 + self._textBox1.WordWrap = False + # + # splitContainer1 + # + self._splitContainer1.Dock = System.Windows.Forms.DockStyle.Top + self._splitContainer1.Location = System.Drawing.Point(0, 0) + self._splitContainer1.Name = "splitContainer1" + self._splitContainer1.Orientation = System.Windows.Forms.Orientation.Horizontal + # + # splitContainer1.Panel1 + # + self._splitContainer1.Panel1.Controls.Add(self._label2) + self._splitContainer1.Panel1.Controls.Add(self._progressBar1) + self._splitContainer1.Panel1.Controls.Add(self._label1) + # + # splitContainer1.Panel2 + # + self._splitContainer1.Panel2.Controls.Add(self._textBox1) + self._splitContainer1.Size = System.Drawing.Size(526, 283) + self._splitContainer1.SplitterDistance = 68 + self._splitContainer1.TabIndex = 4 + # + # runProcess + # + self.ClientSize = System.Drawing.Size(526, 318) + self.Controls.Add(self._splitContainer1) + self.Controls.Add(self._btnCancel) + self.Name = "runProcess" + self.Text = "runProcess" + self.Shown += self.RunProcessShown + self._splitContainer1.Panel1.ResumeLayout(False) + self._splitContainer1.Panel2.ResumeLayout(False) + self._splitContainer1.Panel2.PerformLayout() + self._splitContainer1.EndInit() + self._splitContainer1.ResumeLayout(False) + self.ResumeLayout(False) + + def BgwProcessDoWork(self, sender, e): + collection = e.Argument[0] + books = e.Argument[1] + + count = 0 + bookTouchCount = 0 + fieldTouchCount = 0 + + userVariables = Dictionary[str,str]() + + strReport = '' + + if System.IO.File.Exists(dmGlobals.LOGFILE): + System.IO.File.Delete(dmGlobals.LOGFILE) + + dtStart = System.DateTime.Now + dmGlobals.WriteStartTime() + while count < len(books): + tmpDic = dmGlobals.CreateBookDict(books[count]) + if not self._bgwProcess.CancellationPending: + self._bgwProcess.ReportProgress((100 / len(books)) * count + 1, [count, books[count]]) + if dmGlobals.TraceGeneralMessages: print 'Processing Ruleset Collection' + bookReport = collection.ProcessBook(books[count], self._bgwProcess) + if bookReport != '': + strReport = dmGlobals.AppendReport(strReport, bookReport) + bookTouchCount = bookTouchCount + 1 + fieldTouchCount = fieldTouchCount + dmGlobals.GetTouchCount(books[count], tmpDic) + count = count + 1 + + + #add touch count to log + strReport = strReport + System.Environment.NewLine + System.Environment.NewLine + bookTouchCount.ToString() + ' Books were modified. ' + fieldTouchCount.ToString() + ' Values were changed' + self._bgwProcess.ReportProgress(100, [count, strReport]) + + #write out report + if strReport!= '': + System.IO.File.WriteAllText(dmGlobals.LOGFILE, strReport) + + dmGlobals.WriteEndTime() + duration = System.DateTime.Now - dtStart + strDuration = duration.ToString('hh\:mm\:ss\.ffff') + dmGlobals.WriteDurationtime(strDuration) + + pass + + def BgwProcessProgressChanged(self, sender, e): + progress = e.ProgressPercentage + self.SetProgress(progress, e.UserState) + pass + + def SetProgress(self, progress, userState): + if self.InvokeRequired: + self.Invoke(self.SetProgress, [progress, userState]) + return + + self._progressBar1.Value = progress + if isinstance(userState, list): + if isinstance(userState[1], str): + self._textBox1.Text = userState[1] + else: + self._label2.Text = userState[1].CaptionWithoutTitle + + count = userState[0] + booklen = len(self.Books) + booklen = booklen.ToString() + bookcount = count.ToString() + + self._progressBar1.Value = progress + self._label1.Text = 'Processing ' + bookcount + ' of '+ booklen +' books' + pass + + def BtnCancelClick(self,sender, e): + if self._bgwProcess.IsBusy: + self._bgwProcess.CancelAsync() + else: + self.Close() + + def BgwProcessRunWorkerCompleted(self, sender, e): + self._btnCancel.Text = 'Close' + + def RunProcessShown(self, sender, e): + if len(self.Books) > 0: + self._btnCancel.Text = 'Cancel' + if self._btnCancel.Click == None: + self._btnCancel.Click += self.BtnCancelClick + self._bgwProcess.RunWorkerAsync([self.Collection, self.Books]) + else: + strMessage = 'The following issues need to be attended to\r\n before you can run Data Manager:' + strMessage = strMessage + '\r\n no books are selected' MessageBox.Show(strMessage, 'Not Enough Info') \ No newline at end of file From a0c5062de322b033f3b7b82bcec81f61059d9e64 Mon Sep 17 00:00:00 2001 From: Patrick Aikens Date: Wed, 10 Jan 2018 15:16:43 -0500 Subject: [PATCH 2/3] Fix error with comparing dates in Greater and Less - the compare value is already a datetime, no need to convert it --- dmClasses.py | 2 - dmGlobals.py | 166 +++++++++++++++++++++++++-------------------------- 2 files changed, 83 insertions(+), 85 deletions(-) diff --git a/dmClasses.py b/dmClasses.py index c40597f..b7e66d3 100644 --- a/dmClasses.py +++ b/dmClasses.py @@ -1117,7 +1117,6 @@ def Greater(self, book): elif self.Field in dmGlobals.FIELDSDATETIME: try: - compareValue = dmGlobals.StringToDate(compareValue) return getValue > compareValue except: raise Exception('could not convert \'' + self.Value + '\' to Date') @@ -1187,7 +1186,6 @@ def Less(self, book): elif self.Field in dmGlobals.FIELDSDATETIME: try: - compareValue = dmGlobals.StringToDate(compareValue) return getValue < compareValue except: raise Exception('could not convert \'' + self.Value + '\' to Date') diff --git a/dmGlobals.py b/dmGlobals.py index 3f089ce..fd34ede 100644 --- a/dmGlobals.py +++ b/dmGlobals.py @@ -22,7 +22,7 @@ ERRFILE = Path.Combine(FOLDER, 'dataMan.err') TMPFILE = Path.Combine(FOLDER, 'dataMan.tmp') LOGFILE = Path.Combine(FOLDER, 'dataMan.log') -CHKFILE = Path.Combine(FOLDER, 'dataMan.chk') # will be created once the configuration is saved +CHKFILE = Path.Combine(FOLDER, 'dataMan.chk') # will be created once the configuration is saved GUIEXE = Path.Combine(FOLDER, 'crdmgui.exe') ##############End Set Paths############## @@ -150,10 +150,10 @@ def IsFloat(value): return isinstance(value, float) def CRStringToList(strList): - return strList.Split(Array[str](CRLISTDELIMITER), StringSplitOptions.RemoveEmptyEntries) + return strList.Split(Array[str](CRLISTDELIMITER), StringSplitOptions.RemoveEmptyEntries) def DMStringToList(strList): - return strList.split(DMLISTDELIMITER) + return strList.split(DMLISTDELIMITER) def IsList(value): return isinstance(value, list) or isinstance(value, Array[str]) @@ -226,95 +226,95 @@ def ToString(obj): #######Field And Modifier helpers############## def ValidModifiers(strKey, strRuleOrAction): - strListReturn = [] - if strRuleOrAction.lower() == 'rule': - strListReturn = ValidKeyModifiers(strKey) - elif strRuleOrAction.lower() == 'action': - strListReturn = ValidValModifiers(strKey) - return strListReturn + strListReturn = [] + if strRuleOrAction.lower() == 'rule': + strListReturn = ValidKeyModifiers(strKey) + elif strRuleOrAction.lower() == 'action': + strListReturn = ValidValModifiers(strKey) + return strListReturn def ValidKeyModifiers(strKey): - strListReturn = [] - if KeyFieldType(strKey) == 'STRING': - strListReturn = ALLOWEDKEYMODIFIERSSTRING - elif KeyFieldType(strKey) == 'LIST': - strListReturn = ALLOWEDKEYMODIFIERSLIST - elif KeyFieldType(strKey) == 'DATETIME': - strListReturn = ALLOWEDKEYMODIFIERSDATETIME - elif KeyFieldType(strKey) == 'BOOL': - strListReturn = ALLOWEDKEYMODIFIERSBOOL - elif KeyFieldType(strKey) == 'YESNO': - strListReturn = ALLOWEDKEYMODIFIERSYESNO - elif KeyFieldType(strKey) == 'NUMERIC': - strListReturn = ALLOWEDKEYMODIFIERSNUMERIC - elif KeyFieldType(strKey) == 'PSUEDONUMERIC': - strListReturn = ALLOWEDKEYMODIFIERSNUMERIC - elif KeyFieldType(strKey) == 'LANGUAGEISO': - strListReturn = ALLOWEDKEYMODIFIERSLANGUAGEISO - return strListReturn + strListReturn = [] + if KeyFieldType(strKey) == 'STRING': + strListReturn = ALLOWEDKEYMODIFIERSSTRING + elif KeyFieldType(strKey) == 'LIST': + strListReturn = ALLOWEDKEYMODIFIERSLIST + elif KeyFieldType(strKey) == 'DATETIME': + strListReturn = ALLOWEDKEYMODIFIERSDATETIME + elif KeyFieldType(strKey) == 'BOOL': + strListReturn = ALLOWEDKEYMODIFIERSBOOL + elif KeyFieldType(strKey) == 'YESNO': + strListReturn = ALLOWEDKEYMODIFIERSYESNO + elif KeyFieldType(strKey) == 'NUMERIC': + strListReturn = ALLOWEDKEYMODIFIERSNUMERIC + elif KeyFieldType(strKey) == 'PSUEDONUMERIC': + strListReturn = ALLOWEDKEYMODIFIERSNUMERIC + elif KeyFieldType(strKey) == 'LANGUAGEISO': + strListReturn = ALLOWEDKEYMODIFIERSLANGUAGEISO + return strListReturn def ValidValModifiers(strKey): - strListReturn = [] - if KeyFieldType(strKey) == 'STRING': - strListReturn = ALLOWEDVALMODIFIERSSTRING - elif KeyFieldType(strKey) == 'LIST': - strListReturn = ALLOWEDVALMODIFIERSLIST - elif KeyFieldType(strKey) == 'DATETIME': - strListReturn = ALLOWEDVALMODIFIERSDATETIME - elif KeyFieldType(strKey) == 'BOOL': - strListReturn = ALLOWEDVALMODIFIERSBOOL - elif KeyFieldType(strKey) == 'YESNO': - strListReturn = ALLOWEDVALMODIFIERSYESNO - elif KeyFieldType(strKey) == 'NUMERIC': - strListReturn = ALLOWEDVALMODIFIERSNUMERIC - elif KeyFieldType(strKey) == 'PSUEDONUMERIC': - strListReturn = ALLOWEDVALMODIFIERSNUMERIC - elif KeyFieldType(strKey) == 'LANGUAGEISO': - strListReturn = ALLOWEDVALMODIFIERSLANGUAGEISO - if strKey in REGEXVARREPLACEKEYS: - strListReturn.append('RegExVarReplace') - strListReturn.append('RegExVarAppend') - return strListReturn + strListReturn = [] + if KeyFieldType(strKey) == 'STRING': + strListReturn = ALLOWEDVALMODIFIERSSTRING + elif KeyFieldType(strKey) == 'LIST': + strListReturn = ALLOWEDVALMODIFIERSLIST + elif KeyFieldType(strKey) == 'DATETIME': + strListReturn = ALLOWEDVALMODIFIERSDATETIME + elif KeyFieldType(strKey) == 'BOOL': + strListReturn = ALLOWEDVALMODIFIERSBOOL + elif KeyFieldType(strKey) == 'YESNO': + strListReturn = ALLOWEDVALMODIFIERSYESNO + elif KeyFieldType(strKey) == 'NUMERIC': + strListReturn = ALLOWEDVALMODIFIERSNUMERIC + elif KeyFieldType(strKey) == 'PSUEDONUMERIC': + strListReturn = ALLOWEDVALMODIFIERSNUMERIC + elif KeyFieldType(strKey) == 'LANGUAGEISO': + strListReturn = ALLOWEDVALMODIFIERSLANGUAGEISO + if strKey in REGEXVARREPLACEKEYS: + strListReturn.append('RegExVarReplace') + strListReturn.append('RegExVarAppend') + return strListReturn def KeyFieldType(strKey): - strReturn = 'UNKNOWN' - - if strKey in FIELDSSTRING: - strReturn = 'STRING' - elif strKey in FIELDSLIST: - strReturn = 'LIST' - elif strKey in FIELDSDATETIME: - strReturn = 'DATETIME' - elif strKey in FIELDSBOOL: - strReturn = 'BOOL' - elif strKey in FIELDSYESNO: - strReturn = 'YESNO' - elif strKey in FIELDSMANGAYESNO: - strReturn = 'MANGAYESNO' - elif strKey in FILEDSNUMERIC: - strReturn = 'NUMERIC' - elif strKey in FIELDSPSUEDONUMERIC: - strReturn = 'PSUEDONUMERIC' - elif strKey in FIELDSLANGUAGEISO: - strReturn = 'LANGUAGEISO' - return strReturn + strReturn = 'UNKNOWN' + + if strKey in FIELDSSTRING: + strReturn = 'STRING' + elif strKey in FIELDSLIST: + strReturn = 'LIST' + elif strKey in FIELDSDATETIME: + strReturn = 'DATETIME' + elif strKey in FIELDSBOOL: + strReturn = 'BOOL' + elif strKey in FIELDSYESNO: + strReturn = 'YESNO' + elif strKey in FIELDSMANGAYESNO: + strReturn = 'MANGAYESNO' + elif strKey in FILEDSNUMERIC: + strReturn = 'NUMERIC' + elif strKey in FIELDSPSUEDONUMERIC: + strReturn = 'PSUEDONUMERIC' + elif strKey in FIELDSLANGUAGEISO: + strReturn = 'LANGUAGEISO' + return strReturn def GetAvailableKeys(strRuleOrAction): - strListReturn = [] - if strRuleOrAction.lower() == 'rule': - strListReturn.extend(ALLOWEDKEYS) - elif strRuleOrAction == 'action': - strListReturn.extend(ALLOWEDVALS) - strListReturn.extend(REGEXVARREPLACEKEYS) - return strListReturn + strListReturn = [] + if strRuleOrAction.lower() == 'rule': + strListReturn.extend(ALLOWEDKEYS) + elif strRuleOrAction == 'action': + strListReturn.extend(ALLOWEDVALS) + strListReturn.extend(REGEXVARREPLACEKEYS) + return strListReturn def GetAppendString(strKey): - if strKey in FIELDSMULTILINE: - return "\r\n" - else: - return ", " + if strKey in FIELDSMULTILINE: + return "\r\n" + else: + return ", " - pass + pass def GetValueType(strFieldName): strReturn = unknown @@ -340,7 +340,7 @@ def GetValueType(strFieldName): return strReturn def ComicVineFields(): - return ['Series','Volume','Number','Title','Published','ReleasedTime','AlternateSeries','Publisher','Imprint','Writer','Penciller','Colorist','Inker','Letterer','CoverArtist','Editor','Summary','Characters'] + return ['Series','Volume','Number','Title','Published','ReleasedTime','AlternateSeries','Publisher','Imprint','Writer','Penciller','Colorist','Inker','Letterer','CoverArtist','Editor','Summary','Characters'] #######Field And Modifier helpers############## @@ -469,4 +469,4 @@ def __init__(strMessage, dmContainerParent): class dmCollectionCompileError(dmNodeCompileException): def __init__(self, strMessage, dmNodeParent): - dmNodeCompileException.__init__(self, strMessage, dmNodeParent) \ No newline at end of file + dmNodeCompileException.__init__(self, strMessage, dmNodeParent) From 6a750b5dde5ab0eabba8c61f0e7e3e395bce4e63 Mon Sep 17 00:00:00 2001 From: Patrick Aikens Date: Wed, 10 Jan 2018 15:18:07 -0500 Subject: [PATCH 3/3] Fix typo in Range comparison for dates --- dmClasses.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dmClasses.py b/dmClasses.py index b7e66d3..aa63dd1 100644 --- a/dmClasses.py +++ b/dmClasses.py @@ -1211,7 +1211,7 @@ def Range(self, book): maxVal = dmGlobals.StringToFloat(maxVal) elif self.Field in dmGlobals.FIELDSDATETIME: minVal = System.DateTime.Parse(minVal) - maxVal = System.DateTime.Parse(minVal + ' 23:59:59') + maxVal = System.DateTime.Parse(maxVal + ' 23:59:59') if getValue >= minVal and getValue <= maxVal: return True return False