def postprocess(self): """Parse the converted text to identify chapters and scenes. """ sceneText = [] scId = '' chId = '' inScene = False for line in self._lines: if '[ScID' in line: scId = re.search('[0-9]+', line).group() self.scenes[scId] = Scene() self.chapters[chId].srtScenes.append(scId) inScene = True elif '[/ScID' in line: self.scenes[scId].sceneContent = '\n'.join(sceneText) sceneText = [] inScene = False elif '[ChID' in line: chId = re.search('[0-9]+', line).group() self.chapters[chId] = Chapter() self.srtChapters.append(chId) elif '[/ChID' in line: pass elif inScene: sceneText.append(line)
def handle_starttag(self, tag, attrs): if tag in ('h1', 'h2'): self._scId = None self._lines = [] self._chCount += 1 self._chId = str(self._chCount) self.chapters[self._chId] = Chapter() self.chapters[self._chId].srtScenes = [] self.srtChapters.append(self._chId) self.chapters[self._chId].oldType = '0' if tag == 'h1': self.chapters[self._chId].chLevel = 1 else: self.chapters[self._chId].chLevel = 0 elif tag == 'p': if self._scId is None and self._chId is not None: self._lines = [] self._scCount += 1 self._scId = str(self._scCount) self.scenes[self._scId] = Scene() self.chapters[self._chId].srtScenes.append(self._scId) self.scenes[self._scId].status = '1' self.scenes[self._scId].title = 'Scene ' + str(self._scCount) elif tag == 'div': self._scId = None self._chId = None elif tag == 'meta': if attrs[0][1].lower() == 'author': self.author = attrs[1][1] if attrs[0][1].lower() == 'description': self.desc = attrs[1][1] elif tag == 'title': self._lines = []
def handle_starttag(self, tag, attrs): if tag in ('h1', 'h2'): self._scId = None self._lines = [] self._chCount += 1 self._chId = str(self._chCount) self.chapters[self._chId] = Chapter() self.chapters[self._chId].srtScenes = [] self.srtChapters.append(self._chId) self.chapters[self._chId].oldType = '0' if tag == 'h1': self.chapters[self._chId].chLevel = 1 else: self.chapters[self._chId].chLevel = 0 elif tag == 'h3': self._lines = [] self._scCount += 1 self._scId = str(self._scCount) self.scenes[self._scId] = Scene() self.chapters[self._chId].srtScenes.append(self._scId) self.scenes[self._scId].sceneContent = '' self.scenes[self._scId].status = Scene.STATUS.index('Outline') elif tag == 'div': self._scId = None self._chId = None elif tag == 'meta': if attrs[0][1].lower() == 'author': self.author = attrs[1][1] if attrs[0][1].lower() == 'description': self.desc = attrs[1][1] elif tag == 'title': self._lines = []
def handle_starttag(self, tag, attrs): """Identify scenes and chapters. Override HTMLparser.handle_starttag(). This method is applicable to HTML files that are divided into chapters and scenes. For differently structured HTML files do override this method in a subclass. """ if tag == 'div': if attrs[0][0] == 'id': if attrs[0][1].startswith('ScID'): self._scId = re.search('[0-9]+', attrs[0][1]).group() self.scenes[self._scId] = Scene() self.chapters[self._chId].srtScenes.append(self._scId) elif attrs[0][1].startswith('ChID'): self._chId = re.search('[0-9]+', attrs[0][1]).group() self.chapters[self._chId] = Chapter() self.chapters[self._chId].srtScenes = [] self.srtChapters.append(self._chId)
def read(self): """Parse the file and get the instance variables. Return a message beginning with the ERROR constant in case of error. """ LOW_WORDCOUNT = 10 # Defines the difference between "Outline" and "Draft" def write_scene_content(scId, lines): if scId is not None: text = '\n'.join(lines) self.scenes[scId].sceneContent = text if self.scenes[scId].wordCount < LOW_WORDCOUNT: self.scenes[scId].status = Scene.STATUS.index('Outline') else: self.scenes[scId].status = Scene.STATUS.index('Draft') chCount = 0 scCount = 0 lines = [] chId = None scId = None try: with open(self.filePath, encoding='utf-8') as f: mdText = f.read() cnvText = self._convert_to_yw(mdText) mdLines = (cnvText).split('\n') except (FileNotFoundError): return f'{ERROR}"{os.path.normpath(self.filePath)}" not found.' except: return f'{ERROR}Can not parse "{os.path.normpath(self.filePath)}".' if self._markdownMode: commentStart = '<!---' commentEnd = '--->' else: commentStart = '/*' commentEnd = '*/' for mdLine in mdLines: if mdLine.startswith('#'): # Write previous scene. write_scene_content(scId, lines) scId = None # Add a chapter. chCount += 1 chId = str(chCount) self.chapters[chId] = Chapter() title = mdLine.split('# ')[1] self.chapters[chId].title = title self.srtChapters.append(chId) self.chapters[chId].oldType = '0' if mdLine.startswith('# '): self.chapters[chId].chLevel = 1 else: self.chapters[chId].chLevel = 0 self.chapters[chId].srtScenes = [] elif self.SCENE_DIVIDER in mdLine: # Write previous scene. write_scene_content(scId, lines) scId = None elif scId is not None: lines.append(mdLine) elif mdLine and chId is not None: # Add a scene; drop the first line if empty. scCount += 1 scId = str(scCount) self.scenes[scId] = Scene() self.chapters[chId].srtScenes.append(scId) self.scenes[scId].status = '1' self.scenes[scId].title = f'Scene {scCount}' if self._sceneTitles and mdLine.startswith(commentStart): # The scene title is prefixed as a comment. try: scTitle, scContent = mdLine.split(sep=commentEnd, maxsplit=1) self.scenes[scId].title = scTitle.lstrip(commentStart) lines = [scContent] except: lines = [mdLine] else: lines = [mdLine] return 'Markdown formatted text converted to novel structure.'
def read(self): """Parse the csv file located at filePath, fetching the Scene attributes contained. Return a message beginning with SUCCESS or ERROR. Extend the superclass method. """ message = super().read() if message.startswith('ERROR'): return message for cells in self.rows: i = 0 if 'ScID:' in cells[i]: scId = re.search('ScID\:([0-9]+)', cells[0]).group(1) self.scenes[scId] = Scene() i += 1 self.scenes[scId].title = cells[i] i += 1 self.scenes[scId].desc = self.convert_to_yw(cells[i]) i += 1 self.scenes[scId].tags = self.get_list(cells[i]) i += 1 self.scenes[scId].sceneNotes = self.convert_to_yw(cells[i]) i += 1 if Scene.REACTION_MARKER.lower() in cells[i].lower(): self.scenes[scId].isReactionScene = True else: self.scenes[scId].isReactionScene = False i += 1 self.scenes[scId].goal = cells[i] i += 1 self.scenes[scId].conflict = cells[i] i += 1 self.scenes[scId].outcome = cells[i] i += 1 # Don't write back sceneCount i += 1 # Don't write back wordCount i += 1 # Transfer scene ratings; set to 1 if deleted if cells[i] in self._SCENE_RATINGS: self.scenes[scId].field1 = cells[i] else: self.scenes[scId].field1 = '1' i += 1 if cells[i] in self._SCENE_RATINGS: self.scenes[scId].field2 = cells[i] else: self.scenes[scId].field2 = '1' i += 1 if cells[i] in self._SCENE_RATINGS: self.scenes[scId].field3 = cells[i] else: self.scenes[scId].field3 = '1' i += 1 if cells[i] in self._SCENE_RATINGS: self.scenes[scId].field4 = cells[i] else: self.scenes[scId].field4 = '1' i += 1 # Don't write back scene words total i += 1 # Don't write back scene letters total i += 1 try: self.scenes[scId].status = Scene.STATUS.index(cells[i]) except ValueError: pass # Scene status remains None and will be ignored when # writing back. i += 1 ''' Cannot write back character IDs, because self.characters is None charaNames = self.get_list(cells[i]) self.scenes[scId].characters = [] for charaName in charaNames: for id, name in self.characters.items(): if name == charaName: self.scenes[scId].characters.append(id) ''' i += 1 ''' Cannot write back location IDs, because self.locations is None locaNames = self.get_list(cells[i]) self.scenes[scId].locations = [] for locaName in locaNames: for id, name in self.locations.items(): if name == locaName: self.scenes[scId].locations.append(id) ''' i += 1 ''' Cannot write back item IDs, because self.items is None itemNames = self.get_list(cells[i]) self.scenes[scId].items = [] for itemName in itemNames: for id, name in self.items.items(): if name == itemName: self.scenes[scId].items.append(id) ''' return 'SUCCESS: Data read from "' + os.path.normpath( self.filePath) + '".'
def read(self): """Parse the csv file located at filePath, fetching the Scene attributes contained. Return a message beginning with SUCCESS or ERROR. Extend the superclass method. """ message = super().read() if message.startswith('ERROR'): return message tableHeader = self.rows[0] for cells in self.rows: if 'ChID:' in cells[0]: chId = re.search('ChID\:([0-9]+)', cells[0]).group(1) self.chapters[chId] = Chapter() self.chapters[chId].title = cells[1] self.chapters[chId].desc = self.convert_to_yw(cells[4]) if 'ScID:' in cells[0]: scId = re.search('ScID\:([0-9]+)', cells[0]).group(1) self.scenes[scId] = Scene() self.scenes[scId].tags = self.get_list(cells[2]) self.scenes[scId].title = cells[3] self.scenes[scId].sceneNotes = self.convert_to_yw(cells[4]) i = 5 # Don't write back sceneCount i += 1 # Don't write back wordCount i += 1 # Transfer scene ratings; set to 1 if deleted if cells[i] in self._SCENE_RATINGS: self.scenes[scId].field1 = cells[i] elif tableHeader[i] != self._NOT_APPLICABLE: self.scenes[scId].field1 = '1' i += 1 if cells[i] in self._SCENE_RATINGS: self.scenes[scId].field2 = cells[i] elif tableHeader[i] != self._NOT_APPLICABLE: self.scenes[scId].field2 = '1' i += 1 if cells[i] in self._SCENE_RATINGS: self.scenes[scId].field3 = cells[i] elif tableHeader[i] != self._NOT_APPLICABLE: self.scenes[scId].field3 = '1' i += 1 if cells[i] in self._SCENE_RATINGS: self.scenes[scId].field4 = cells[i] elif tableHeader[i] != self._NOT_APPLICABLE: self.scenes[scId].field4 = '1' return 'SUCCESS: Data read from "' + os.path.normpath(self.filePath) + '".'
def create_scene(sceneId, parent, splitCount): """Create a new scene and add it to the novel. """ WARNING = ' (!) ' newScene = Scene() if parent.title: if len(parent.title) > self.CLIP_TITLE: title = parent.title[:self.CLIP_TITLE] + '...' else: title = parent.title newScene.title = title + ' Split: ' + str(splitCount) else: newScene.title = 'New scene Split: ' + str(splitCount) if parent.desc and not parent.desc.startswith(WARNING): parent.desc = WARNING + parent.desc if parent.goal and not parent.goal.startswith(WARNING): parent.goal = WARNING + parent.goal if parent.conflict and not parent.conflict.startswith(WARNING): parent.conflict = WARNING + parent.conflict if parent.outcome and not parent.outcome.startswith(WARNING): parent.outcome = WARNING + parent.outcome # Reset the parent's status to Draft, if not Outline. if parent.status > 2: parent.status = 2 newScene.status = parent.status newScene.isNotesScene = parent.isNotesScene newScene.isUnused = parent.isUnused newScene.isTodoScene = parent.isTodoScene newScene.date = parent.date newScene.time = parent.time newScene.day = parent.day newScene.hour = parent.hour newScene.minute = parent.minute newScene.lastsDays = parent.lastsDays newScene.lastsHours = parent.lastsHours newScene.lastsMinutes = parent.lastsMinutes ywPrj.scenes[sceneId] = newScene