class Thread: def __init__(self, prompt, datastore, theme, patterns_map): self.workers_count = len(datastore.cpu_threads_requested_entry) self.indentation_level = "│ " self.patterns_map = patterns_map self.datastore = datastore self.enable_jsonld = datastore.blog_configuration["enable_jsonld"] self.path_encoding = datastore.blog_configuration["path_encoding"] # Notify wich thread is processed if prompt != "": notify("├─ " + prompt) self.forbidden = patterns_map.non_contextual_entries_keys self.entries_per_page = int( datastore.blog_configuration["entries_per_pages"]) self.disable_threads = datastore.disable_threads # Setup useful data self.theme = theme self.footer = deepcopy(self.theme.footer) self.header = deepcopy(self.theme.header) self.entry = deepcopy(self.theme.entry) self.context_header = "header.html" self.context_footer = "footer.html" self.content_type = "html" self.column_opening = '<div id="__VENC_COLUMN_{0}__" class="__VENC_COLUMN__">' self.column_closing = "</div>" self.columns_number = self.datastore.blog_configuration["columns"] self.thread_name = "" self.rss_feed = None self.atom_feed = None # Setup pattern processor self.processor = Processor(self.workers_count) for pattern_name in patterns_map.contextual["functions"].keys(): self.processor.set_function( pattern_name, patterns_map.contextual["functions"][pattern_name]) for pattern_name in patterns_map.contextual["names"].keys(): self.processor.set_function( pattern_name, getattr(self, patterns_map.contextual["names"][pattern_name])) def path_encode(self, path): if self.path_encoding in ["utf-8", '']: return quirk_encoding(unidecode.unidecode(path)) else: return path def return_page_around(self, string, params): try: return string.format(**params) except KeyError as e: raise UnknownContextual(str(e)[1:-1]) # Must be called in child class def get_relative_location(self, cpu_thread_id, argv): return self.export_path[5:] def get_relative_origin(self, cpu_thread_id, argv): return self.relative_origin def get_thread_name(self, cpu_thread_id, argv): if len(self.thread_name): try: return argv[0].format(**{"value": self.thread_name}) except IndexError: return self.thread_name else: try: return argv[1] except IndexError: return "" # Must be called in child class def organize_entries(self, entries): self.pages = list() for i in range(0, ceil(len(entries) / self.entries_per_page)): self.pages.append(entries[i * self.entries_per_page:(i + 1) * self.entries_per_page]) self.pages_count = len(self.pages) # Must be called in child class def get_next_page(self, cpu_thread_id, argv): if self.current_page < self.pages_count - 1: params = { "page_number": str(self.current_page + 1), "entry_id": '', "entry_title": '', "path": '' } if self.in_thread: params["path"] = self.filename.format(**params) else: try: params["path"] = self.current_entry.next_entry.url params["entry_id"] = self.current_entry.next_entry.id params["entry_title"] = self.current_entry.next_entry.title except AttributeError: pass try: return argv[0].format(**params) except KeyError as e: raise UnknownContextual(str(e)[1:-1]) else: return str() # Must be called in child class def get_previous_page(self, cpu_thread_id, argv): if self.current_page > 0: params = { "page_number": str(self.current_page - 1) if self.current_page - 1 != 0 else '', "entry_id": '', "entry_title": '', "path": '' } if self.in_thread: params["path"] = self.filename.format(**params) else: try: params["entry_id"] = self.current_entry.previous_entry.id params[ "entry_title"] = self.current_entry.previous_entry.title params["path"] = self.current_entry.previous_entry.url except AttributeError: pass try: return argv[0].format(**params) except KeyError as e: raise UnknownContextual(str(e)[1:-1]) else: return str() # Must be called in child class def for_pages(self, cpu_thread_id, argv): list_lenght = int(argv[0]) string = argv[1] separator = argv[2] if self.pages_count <= 1: return str() output = str() page_number = 0 for page in self.pages: if (not page_number < self.current_page - list_lenght) and ( not page_number > self.current_page + list_lenght): try: output += string.format( **{ "entry_id": '', "entry_title": '', "page_number": str(page_number), "path": self.format_filename(page_number) }) + separator except KeyError as e: raise UnknownContextual(str(e)[1:-1]) page_number += 1 return output[:-len(separator)] def JSONLD(self, cpu_thread_id, argv): return '' def if_pages(self, cpu_thread_id, argv): if self.pages_count > 1: return argv[0].strip() elif len(argv) >= 2: return argv[1].strip() else: return '' def if_in_first_page(self, cpu_thread_id, argv): if self.current_page == 0: return argv[0].strip() elif len(argv) >= 2: return argv[1].strip() else: return '' def if_in_last_page(self, cpu_thread_id, argv): if self.current_page == len(self.pages) - 1: return argv[0].strip() elif len(argv) >= 2: return argv[1].strip() else: return '' def if_in_entry_id(self, cpu_thread_id, argv): if len(argv) >= 3: return argv[2].strip() else: return '' def if_in_main_thread(self, cpu_thread_id, argv): if len(argv) >= 2: return argv[1].strip() else: return '' def if_in_categories(self, cpu_thread_id, argv): if len(argv) >= 2: return argv[1].strip() else: return '' def if_in_archives(self, cpu_thread_id, argv): if len(argv) >= 2: return argv[1].strip() else: return '' def if_in_thread(self, cpu_thread_id, argv): if self.in_thread: return argv[0].strip() elif len(argv) >= 2: return argv[1].strip() else: return '' def if_in_feed(self, cpu_thread_id, argv): if len(argv) >= 2: return argv[1].strip() else: return '' def if_in_thread_and_has_feeds(self, cpu_thread_id, argv): return argv[0] if self.thread_has_feeds else ( "" if len(argv) <= 1 else argv[1]) def format_filename(self, value): try: if value == 0: return self.path_encode( self.filename.format(**{'page_number': ''})) else: return self.path_encode( self.filename.format(**{'page_number': value})) except KeyError as e: from venc2.prompt import die die(messages.variable_error_in_filename.format(str(e))) # Overridden in child class (EntriesThread) def setup_context(self, entry): self.current_entry = entry def write_file(self, output, file_id): if self.in_thread: format_value = file_id else: format_value = page[0].id stream = codecs.open(self.export_path + '/' + self.format_filename(format_value), 'w', encoding="utf-8") stream.write(output.replace("\x1a", self.relative_origin)) stream.close() def pre_iteration(self): global current_source self.processor.blacklist = self.forbidden current_source = self.header self.processor.process(current_source, safe_process=True) self.output = current_source.string current_source.restore() self.processor.blacklist = [] self.columns_counter = 0 self.columns = ['' for i in range(0, self.columns_number)] def post_iteration(self): global current_source self.columns_counter = 0 for column in self.columns: self.output += self.column_opening.format( self.columns_counter) + column + self.column_closing self.processor.blacklist = self.forbidden current_source = self.footer self.processor.process(current_source, safe_process=True) self.output += current_source.string self.footer.restore() self.write_file(self.output.replace("\x1a", self.relative_origin), self.page_number) self.page_number += 1 self.current_page = self.page_number def do_iteration(self, entry): global current_source entry_wrapper = getattr(entry, self.content_type + "_wrapper") preprocessed_wrapper = getattr(entry, self.content_type + "_wrapper").processed_string self.processor.process(preprocessed_wrapper, safe_process=True) output = preprocessed_wrapper.string if entry_wrapper.process_get_entry_content: self.processor.process(entry.content, safe_process=True) output = output.replace("---VENC-GET-ENTRY-CONTENT---", entry.content.string) if entry_wrapper.process_get_entry_preview: self.processor.process(entry.preview, safe_process=True) output = output.replace("---VENC-GET-ENTRY-PREVIEW---", entry.preview.string) output = output.replace( "---VENC-PREVIEW-IF-IN-THREAD-ELSE-CONTENT---", entry.preview.string if self.in_thread else entry.content.string) self.columns[self.columns_counter] += output preprocessed_wrapper.restore() if entry_wrapper.process_get_entry_content: entry.content.restore() if entry_wrapper.process_get_entry_preview: entry.preview.restore() self.columns_counter += 1 if self.columns_counter >= self.columns_number: self.columns_counter = 0 def iterate_through_pages(self): for page in self.pages: self.pre_iteration() for entry in page: self.setup_context(entry) self.do_iteration(entry) self.post_iteration() # Must be called in child class def do(self): global current_source self.current_page = 0 self.page_number = 0 if self.pages_count == 0: current_source = self.header self.processor.process(current_source) output = current_source.string current_source = self.footer self.processor.process(current_source) output += current_source.string stream = codecs.open(self.export_path + '/' + self.format_filename(0), 'w', encoding="utf-8") stream.write(output.replace("\x1a", self.relative_origin)) stream.close() else: self.iterate_through_pages()
class Thread: def __init__(self, prompt, datastore, theme, patterns_map): self.indentation_level = "│ " self.patterns_map = patterns_map self.datastore = datastore # Notify wich thread is processed if prompt != "": notify("├─ " + prompt) self.forbidden = patterns_map.non_contextual_entries_keys self.entries_per_page = int( datastore.blog_configuration["entries_per_pages"]) self.disable_threads = datastore.disable_threads # Setup useful data self.theme = theme self.footer = deepcopy(self.theme.footer) self.header = deepcopy(self.theme.header) self.entry = deepcopy(self.theme.entry) self.context_header = "header.html" self.context_footer = "footer.html" self.content_type = "html" self.column_opening = '<div id="__VENC_COLUMN_{0}__" class="__VENC_COLUMN__">' self.column_closing = "</div>" self.columns_number = self.datastore.blog_configuration["columns"] # Setup pattern processor self.processor = Processor() for pattern_name in patterns_map.contextual["functions"].keys(): self.processor.set_function( pattern_name, patterns_map.contextual["functions"][pattern_name]) for pattern_name in patterns_map.contextual["names"].keys(): self.processor.set_function( pattern_name, getattr(self, patterns_map.contextual["names"][pattern_name])) def return_page_around(self, string, params): return string.format(**params) # Must be called in child class def get_relative_location(self, argv): return self.export_path[5:] # Must be called in child class def organize_entries(self, entries): self.pages = list() for i in range(0, ceil(len(entries) / self.entries_per_page)): self.pages.append(entries[i * self.entries_per_page:(i + 1) * self.entries_per_page]) self.pages_count = len(self.pages) # Must be called in child class def get_next_page(self, argv): if self.current_page < self.pages_count - 1: params = { "page_number": str(self.current_page + 1), "entry_id": '', "entry_title": '', "path": '' } if self.in_thread: params["path"] = self.filename.format(**params) else: try: params["path"] = self.current_entry.next_entry.url params["entry_id"] = self.current_entry.next_entry.id params["entry_title"] = self.current_entry.next_entry.title except AttributeError: pass return argv[0].format(**params) else: return str() # Must be called in child class def get_previous_page(self, argv): if self.current_page > 0: params = { "page_number": str(self.current_page - 1) if self.current_page - 1 != 0 else '', "entry_id": '', "entry_title": '', "path": '' } if self.in_thread: params["path"] = self.filename.format(**params) else: try: params["entry_id"] = self.current_entry.previous_entry.id params[ "entry_title"] = self.current_entry.previous_entry.title params["path"] = self.current_entry.previous_entry.url except AttributeError: pass return argv[0].format(**params) else: return str() # Must be called in child class def for_pages(self, argv): list_lenght = int(argv[0]) string = argv[1] separator = argv[2] if self.pages_count <= 1: return str() output = str() page_number = 0 for page in self.pages: if (not page_number < self.current_page - list_lenght) and ( not page_number > self.current_page + list_lenght): try: output += string.format( **{ "entry_id": '', "entry_title": '', "page_number": str(page_number), "path": self.filename.format( **{ "page_number": (str() if page_number == 0 else page_number) }) }) + separator except KeyError as e: print(e) raise PatternInvalidArgument(name="string", value=string) page_number += 1 return output[:-len(separator)] def JSONLD(self, argv): return '' def if_in_first_page(self, argv): if self.current_page == 0: return argv[0].strip() else: return argv[1].strip() def if_in_last_page(self, argv): if self.current_page == len(self.pages) - 1: return argv[0].strip() else: return argv[1].strip() def if_in_entry_id(self, argv): return argv[2].strip() def if_in_categories(self, argv): return argv[1].strip() def if_in_archives(self, argv): return argv[1].strip() def if_in_thread(self, argv): if self.in_thread: return argv[0].strip() else: return argv[1].strip() def format_filename(self, value): try: if value == 0: return self.filename.format(**{'page_number': ''}) else: return self.filename.format(**{'page_number': value}) except KeyError as e: die(messages.variable_error_in_filename.format(str(e))) # Overridden in child class (EntriesThread) def setup_context(self, entry): self.current_entry = entry def write_file(self, output, file_id): if self.in_thread: format_value = file_id else: format_value = page[0].id stream = codecs.open(self.export_path + '/' + self.format_filename(format_value), 'w', encoding="utf-8") stream.write(output) stream.close() def pre_iteration(self): self.processor.blacklist = self.forbidden self.processor.process(self.header, safe_process=True) self.output = self.header.string self.header.restore() self.processor.blacklist = [] self.columns_counter = 0 self.columns = ['' for i in range(0, self.columns_number)] def post_iteration(self): self.columns_counter = 0 for column in self.columns: self.output += self.column_opening.format( self.columns_counter) + column + self.column_closing self.processor.blacklist = self.forbidden self.processor.process(self.footer, safe_process=True) self.output += self.footer.string self.footer.restore() self.write_file( self.output.replace(".:GetRelativeOrigin:.", self.relative_origin), self.page_number) self.page_number += 1 self.current_page = self.page_number def do_iteration(self, entry): content_header = getattr(entry, self.content_type + "_wrapper").above self.processor.process(content_header, safe_process=True) self.columns[self.columns_counter] += content_header.string content_header.restore() if (entry.html_wrapper.required_content_pattern == ".:GetEntryPreview:.") or ( entry.html_wrapper.required_content_pattern == ".:PreviewIfInThreadElseContent:." and self.in_thread): self.processor.process(entry.preview, safe_process=True) self.columns[self.columns_counter] += entry.preview.string entry.preview.restore() else: self.processor.process(entry.content, safe_process=True) self.columns[self.columns_counter] += entry.content.string entry.content.restore() content_footer = getattr(entry, self.content_type + "_wrapper").below self.processor.process(content_footer, safe_process=True) self.columns[self.columns_counter] += content_footer.string content_footer.restore() self.columns_counter += 1 if self.columns_counter >= self.columns_number: self.columns_counter = 0 def iterate_through_pages(self): for page in self.pages: self.pre_iteration() for entry in page: self.setup_context(entry) self.do_iteration(entry) self.post_iteration() # Must be called in child class def do(self): self.current_page = 0 self.page_number = 0 if self.pages_count == 0: self.processor.process(self.header) output = self.header.string self.processor.process(self.footer) output += self.footer.string stream = codecs.open(self.export_path + '/' + self.format_filename(0), 'w', encoding="utf-8") stream.write( output.replace(".:GetRelativeOrigin:.", self.relative_origin)) stream.close() else: self.iterate_through_pages()
class Thread: def __init__(self, prompt, datastore, theme, patterns_map): self.indentation_level = "│ " self.patterns_map = patterns_map self.datastore = datastore # Notify wich thread is processed if prompt != "": notify("├─ "+prompt) self.forbidden = patterns_map.non_contextual_entries_keys self.entries_per_page = int(datastore.blog_configuration["entries_per_pages"]) self.disable_threads = datastore.disable_threads # Setup useful data self.theme = theme self.footer = deepcopy(self.theme.footer) self.header = deepcopy(self.theme.header) self.entry = deepcopy(self.theme.entry) self.context_header = "header.html" self.context_footer = "footer.html" self.content_type = "html" self.column_opening = '<div id="__VENC_COLUMN_{0}__" class="__VENC_COLUMN__">' self.column_closing = "</div>" self.columns_number = self.datastore.blog_configuration["columns"] # Setup pattern processor self.processor = Processor() for pattern_name in patterns_map.contextual["functions"].keys(): self.processor.set_function(pattern_name, patterns_map.contextual["functions"][pattern_name]) for pattern_name in patterns_map.contextual["names"].keys(): self.processor.set_function(pattern_name, getattr(self, patterns_map.contextual["names"][pattern_name])) def return_page_around(self, string, params): return string.format(**params) # Must be called in child class def get_relative_location(self, argv): return self.export_path[5:] # Must be called in child class def organize_entries(self, entries): self.pages = list() for i in range(0, ceil(len(entries)/self.entries_per_page)): self.pages.append( entries[i*self.entries_per_page:(i+1)*self.entries_per_page] ) self.pages_count = len(self.pages) # Must be called in child class def get_next_page(self, argv): if self.current_page < self.pages_count - 1: params = { "page_number" : str(self.current_page + 1), "entry_id" : '', "entry_title": '', "path" : '' } if self.in_thread: params["path"] = self.filename.format(**params) else: try: params["path"] = self.current_entry.next_entry.url params["entry_id"] = self.current_entry.next_entry.id params["entry_title"] = self.current_entry.next_entry.title except AttributeError: pass return argv[0].format(**params) else: return str() # Must be called in child class def get_previous_page(self, argv): if self.current_page > 0: params = { "page_number" : str(self.current_page - 1) if self.current_page - 1 != 0 else '', "entry_id" : '', "entry_title": '', "path" : '' } if self.in_thread: params["path"] = self.filename.format(**params) else: try: params["entry_id"] = self.current_entry.previous_entry.id params["entry_title"] = self.current_entry.previous_entry.title params["path"] = self.current_entry.previous_entry.url except AttributeError: pass return argv[0].format(**params) else: return str() # Must be called in child class def for_pages(self, argv): list_lenght = int(argv[0]) string = argv[1] separator = argv[2] if self.pages_count <= 1: return str() output = str() page_number = 0 for page in self.pages: if (not page_number < self.current_page - list_lenght) and (not page_number > self.current_page + list_lenght): try: output += string.format( **{ "entry_id":'', "entry_title":'', "page_number":str(page_number), "path": self.filename.format(**{"page_number": (str() if page_number == 0 else page_number) }) } ) + separator except KeyError as e: print(e) raise PatternInvalidArgument(name="string", value=string) page_number +=1 return output[:-len(separator)] def JSONLD(self, argv): return '' def if_in_first_page(self, argv): if self.current_page == 0: return argv[0].strip() else: return argv[1].strip() def if_in_last_page(self, argv): if self.current_page == len(self.pages) -1: return argv[0].strip() else: return argv[1].strip() def if_in_entry_id(self, argv): return argv[2].strip() def if_in_categories(self, argv): return argv[1].strip() def if_in_archives(self, argv): return argv[1].strip() def if_in_thread(self, argv): if self.in_thread: return argv[0].strip() else: return argv[1].strip() def format_filename(self, value): try: if value == 0: return self.filename.format(**{ 'page_number':'' }) else: return self.filename.format(**{ 'page_number':value }) except KeyError as e: die(messages.variable_error_in_filename.format(str(e))) # Overridden in child class (EntriesThread) def setup_context(self, entry): self.current_entry = entry def write_file(self, output, file_id): if self.in_thread: format_value = file_id else: format_value = page[0].id stream = codecs.open( self.export_path+'/'+self.format_filename(format_value), 'w', encoding="utf-8" ) stream.write(output) stream.close() def pre_iteration(self): self.processor.blacklist = self.forbidden self.processor.process(self.header, safe_process = True) self.output = self.header.string self.header.restore() self.processor.blacklist = [] self.columns_counter = 0 self.columns = [ '' for i in range(0, self.columns_number) ] def post_iteration(self): self.columns_counter = 0 for column in self.columns: self.output += self.column_opening.format(self.columns_counter)+column+self.column_closing self.processor.blacklist = self.forbidden self.processor.process(self.footer, safe_process = True) self.output += self.footer.string self.footer.restore() self.write_file(self.output.replace(".:GetRelativeOrigin:.", self.relative_origin), self.page_number) self.page_number += 1 self.current_page = self.page_number def do_iteration(self, entry): content_header = getattr(entry,self.content_type+"_wrapper").above self.processor.process(content_header, safe_process = True) self.columns[self.columns_counter] += content_header.string content_header.restore() if (entry.html_wrapper.required_content_pattern == ".:GetEntryPreview:.") or (entry.html_wrapper.required_content_pattern == ".:PreviewIfInThreadElseContent:." and self.in_thread): self.processor.process(entry.preview, safe_process = True) self.columns[self.columns_counter] += entry.preview.string entry.preview.restore() else: self.processor.process(entry.content, safe_process = True) self.columns[self.columns_counter] += entry.content.string entry.content.restore() content_footer = getattr(entry,self.content_type+"_wrapper").below self.processor.process(content_footer, safe_process = True) self.columns[self.columns_counter] += content_footer.string content_footer.restore() self.columns_counter +=1 if self.columns_counter >= self.columns_number: self.columns_counter = 0 def iterate_through_pages(self): for page in self.pages: self.pre_iteration() for entry in page: self.setup_context(entry) self.do_iteration(entry) self.post_iteration() # Must be called in child class def do(self): self.current_page = 0 self.page_number = 0 if self.pages_count == 0: self.processor.process(self.header) output = self.header.string self.processor.process(self.footer) output += self.footer.string stream = codecs.open( self.export_path +'/'+ self.format_filename(0), 'w', encoding="utf-8" ) stream.write(output.replace(".:GetRelativeOrigin:.", self.relative_origin)) stream.close() else: self.iterate_through_pages()