def create_base_folder(path, package_name): """ Create base directory if needed """ basePath = pathlib.Path(path).parent # Check if the base folder is a file if basePath.exists(): # Check if the parent is a file or if its a symlink if basePath.is_file() or basePath.is_symlink(): logging.print_error( "Base directory is a file or link: {}".format(basePath), package_name) return False # If not, it must be a directory, so we are ok else: return True # Create path and parents (or ignore if folder already exists) try: basePath.mkdir(parents=True, exist_ok=True) except Exception as error: logging.print_error( "Could not create parent folder \"{}\" due to following error: {}". format(basePath, error), package_name) return False else: logging.print_verbose( "Parent folder dosent exist and was created: {}".format(basePath), package_name) return True
def main(): """ Main function """ global script global command global args script = str(sys.argv.pop(0)) # get 0 # Welcome logging.print_welcome() # Get the intended command command = get_command() # Execute specified command if command == Command.BUILD: logging.print_info('Building book template.') build_template() elif command == Command.CONVERT: logging.print_info('Converting outline into file structure.') convert_outline() elif command == Command.COMPILE: logging.print_info('Compiling markdown into book.') compile_book() else: logging.print_error('Command selection failed for: ', command)
def cleanup_output(format=None): """ Removes compiled output for the specified format or all output when no format is provided. Parameters: format PDF, EPUB, or HTML; null will empty the entire output directory """ # Execute specified command if format == Format.PDF.value: logging.print_info("Deleting output for PDF.") elif format == Format.EPUB.value: logging.print_info("Deleting output for EPUB.") elif format == Format.HTML.value: logging.print_info("Deleting output for HTML.") else: logging.print_info("Deleting output for all formats.") # cleanup output directories try: cleanup_path = cwd + '/output/' + format if os.path.isdir(cleanup_path) and os.path.exists(cleanup_path): shutil.rmtree(cleanup_path) # except OSError: except OSError as err: logging.print_error("OS error: {0}".format(err)) sys.exit('Output directory cleanup failed:', cleanup_path)
def run(self): print_info('RUNNING TEST: {} ({})'.format(self.filename, self.command)) result = os.system(self.command) if is_command_result_successfull(result): print_success('SUCCESS') self.status = Status.SUCCESS else: print_error('ERROR: {}'.format(result)) self.status = Status.ERROR
def compile_book(): cleanup_media() copy_media_cwd() global output_format output_file_name = 'output' # TODO: replace with book name file_list = [ os.path.join(dp, f) for dp, dn, filenames in os.walk(content_path) for f in filenames if os.path.splitext(f)[1] == '.md' ] file_list = sorted(file_list) output_format_path = str(output_path) + '/' + \ str(output_format.value) + '/' try: cleanup_output(str(output_format.value)) # create content directory if not os.path.exists(output_format_path): os.makedirs(output_format_path) except OSError: sys.exit('Output format directory "' + output_format_path + '" does not exist and cannot be created') output_file = output_format_path + 'output.' + str(output_format.value) # leave out the file list if output_format.value == Format.PDF.value: args = ['pandoc', '--pdf-engine=xelatex', '-s', '-o', str(output_file)] else: args = ['pandoc', '-s', '-o', str(output_file)] # splice in the file list to avoid Pandoc weirdness args[2:2] = file_list try: # run pandoc with the parameters subprocess.check_output(args) except subprocess.CalledProcessError as e: cleanup_media() logging.print_error(e.output) logging.print_error("Pandoc converstion failed: ", str(args)) if (output_format == Format.HTML): copy_media_html() cleanup_media() logging.print_info("Markdown book compiled into " + str(output_format.value).upper() + ": " + output_file)
def create_symlink(source, destination, package_name=None): """ Creates symlink from source to destination """ try: os.symlink(source, destination) except OSError as error: logging.print_error("Unable to create symlink: {}".format(error), package_name) else: logging.print_verbose("Linking {} <-> {}".format(source, destination), package_name)
def compile_book_init(p_output_format): global output_format if p_output_format == Format.PDF.value: output_format = Format.PDF elif p_output_format == Format.EPUB.value: output_format = Format.EPUB elif p_output_format == Format.HTML.value: output_format = Format.HTML else: logging.print_error('Invalid option for output format provided: ' + p_output_format) exit(1)
def create_folder(path, package_name): """ Creates a folder """ try: os.makedirs(path) except OSError as error: logging.print_error( "Could not create folder \"{}\" due to following error: {}".format( path, error), package_name) else: logging.print_verbose( "Folder doesn't exist and was created: {}".format(path), package_name)
def is_project_directory(): """ Determine if the current directory is a Tanagra project directory Returns: True if current working directory is a Tanagra project directory False otherwise """ global command result = False logging.print_info('Checking current working directory (' + cwd + ') for project...') metadata_found = os.path.exists(metadata_path) outline_found = os.path.exists(outline_path) content_found = os.path.exists(content_path) output_found = os.path.exists(output_path) if ((metadata_found is False) and (outline_found is False) and (metadata_found is False) and (outline_found is False)): logging.print_warning( 'Tanagra project not found in current directory: ' + cwd) elif ((metadata_found is False) or (outline_found is False) or (metadata_found is False) or (outline_found is False)): # project not properly initialized logging.print_error('Tanagra project not properly initialized.') if metadata_found is False: logging.print_error(' - metadata.md file not found.') if outline_found is False: logging.print_error(' - outline.md file not found.') if content_found is False: logging.print_error(' - content/ directory not found.') if output_found is False: logging.print_error(' - output/ directory not found.') logging.print_warning( 'Please run Tanagra to build new book template or attempt to resolve issues manually.' ) print('') else: result = True return result
def get_command(): """ Determine that the user is trying to do """ global args command = None if len(sys.argv) > 0: # get the command argument (build, convert, compile) command_arg = str(sys.argv.pop(0)).lower() # get 1 if command_arg == 'build': command = Command.BUILD elif command_arg == 'convert': command = Command.CONVERT elif command_arg == 'compile': command = Command.COMPILE else: logging.print_error('Command arugment is not valid.') exit(1) args = sys.argv # get arguments else: # command argument not provided logging.print_info('Please enter a number to specify a command.') logging.print_info(' [1] Build a new book template') logging.print_info(' [2] Convert outline into file structure') logging.print_info(' [3] Compile markdown files and media into a book') logging.print_info(' [4] Exit Tanagra') command_choice = str(input()) args = [] # make args list empty set as there have been none provided if command_choice == '1': command = Command.BUILD elif command_choice == '2': command = Command.CONVERT elif command_choice == '3': command = Command.COMPILE elif command_choice == '4': exit(0) else: logging.print_error('Failed to enter a valid command selection.') exit(1) return command
def copy_media_html(): """ Copies media folders from cwd to output for HTML post compilation """ media_root_dirs = [] for child in next(os.walk(cwd))[1]: if (os.path.isdir(child)) and child.endswith('_media'): media_root_dirs.append(child) # copy media folders to output try: for media_dir in media_root_dirs: dir_name = os.path.basename(os.path.normpath(media_dir)) shutil.copytree(media_dir, output_path + '/html/' + dir_name) # except OSError: except OSError as err: logging.print_error("OS error: {0}".format(err)) sys.exit('Media directory copy to output failed.')
def copy_media_cwd(): """ Copies media folders from content/ to cwd for compilation """ media_dirs = [] for (root, dirs, files) in os.walk(content_path): if (root.endswith('_media')): media_dirs.append(root) # copy media folders to root try: for media_dir in media_dirs: dir_name = os.path.basename(os.path.normpath(media_dir)) shutil.copytree(media_dir, cwd + '/' + dir_name) # except OSError: except OSError as err: logging.print_error("OS error: {0}".format(err)) sys.exit('Media directory copy to cwd failed.')
def is_converted(): """ Determine if the content directory has already been populated (outline already converted) Returns: True if files exist in the content directory False otherwise """ result = False if os.path.exists(content_path) and os.path.isdir(content_path): if os.listdir(content_path): result = True logging.print_warning('Warning: Content directory is not empty.') else: result = True logging.print_error('Error: Content directory does not exist.') return result
def cleanup_media(): """ Removes copies of media directories from root following compilation """ media_root_dirs = [] for child in next(os.walk(cwd))[1]: if (os.path.isdir(child)) and child.endswith('_media'): media_root_dirs.append(child) # cleanup media directories from root try: for media_root_dir in media_root_dirs: if os.path.isdir(cwd + '/' + media_root_dir) and os.path.exists( cwd + '/' + media_root_dir): logging.print_info('Cleanup: ' + cwd + '/' + media_root_dir) shutil.rmtree(cwd + '/' + media_root_dir) # except OSError: except OSError as err: logging.print_error("OS error: {0}".format(err)) sys.exit('Media directory cleanup failed.')
def start_tests(path='.', log_level=default_log_level): """ Function to run tests at chosen directory Params: path: string - path to chosen directory log_level?: string - one of ERROR, WARNING, INFO, SUCCESS The system logs messages with level not bigger than chosen log_level. For example if chosen level is WARNING - the system will show ERROR and WARNING messages. """ set_log_level(log_level) print_info('Starting...') tests = Test.collect_tests(path) Test.run_tests(tests) failed_tests = Test.get_failed_tests(tests) print_info('Finished!') if len(failed_tests): print_error('Not all tests successfully passed :(') print_error('Failed tests:') for test in failed_tests: print_error(test) else: print_success('All tests successfully pased!')
def compile_book_prompt(): global output_format logging.print_info( 'Please select the output format for your rendered book.') logging.print_info(' [1] PDF') logging.print_info(' [2] EPUB') logging.print_info(' [3] HTML') output_format_choice = str(input()) if not output_format_choice: logging.print_error('Failed to enter a command selection.') exit(1) elif output_format_choice == '1': output_format = Format.PDF elif output_format_choice == '2': output_format = Format.EPUB elif output_format_choice == '3': output_format = Format.HTML else: logging.print_error('Failed to enter a valid output format selection.') exit(1)
def convert_outline(): logging.print_info('Content directory: ' + content_path) logging.print_info('Outline file: ' + output_path) # make sure outline file exists logging.print_info('Loading ' + outline_path + '...') if path.exists(outline_path): logging.print_info('Reading ' + outline_path + '...') else: logging.print_info(outline_path + ' does not exist.') sys.exit(1) # read the outline file with open(outline_path) as f: content = f.readlines() structure = [] # build up structure list with valid lines for line in content: # only grab the line if it starts with markdown list item 1. XXXX if line.lstrip(' ')[0:3] == '1. ': structure.append(line.strip('\n')) # clean out the content structure if os.path.isdir(content_path): for file in os.listdir(content_path): file_path = os.path.join(content_path, file) try: if os.path.isfile(file_path): os.unlink(file_path) elif os.path.isdir(file_path): shutil.rmtree(file_path) except Exception as e: logging.print_error(e) logging.print_info(content_path + ' emptied.') depth = 0 part = '' chapter = '' section = '' subsection = '' for item in structure: if item: depth = (len(item) - len(item.lstrip(' '))) / 3 item = item.lstrip(' ').lstrip('1. ') if depth == 0: # Part part = content_path + '/' + item if not os.path.exists(part): os.makedirs(part) logging.print_info(part) # media folder os.makedirs(part + '/' + item + '_media') if depth == 1: # Chapter logging.print_info(item) chapter = part + '/' + item + '.md' logging.print_info(chapter) mode = 'a+' if os.path.exists(chapter) else 'w+' with open(chapter, mode) as file: file.write('# ' + item + "\n\n") if depth == 2: # Section section = '## ' + item logging.print_info(section) mode = 'a+' if os.path.exists(chapter) else 'w+' with open(chapter, mode) as file: file.write('## ' + item + "\n\n\n") if depth == 3: # Subsection subsection = '### ' + item logging.print_info(subsection) mode = 'a+' if os.path.exists(chapter) else 'w+' with open(chapter, mode) as file: file.write('### ' + item + "\n\n\n")