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(): """ Executes actions to compile a book """ # Look for project in cwd if is_project_directory() is False: logging.print_info('No Tanagra project found in ' + cwd) exit(0) # Look for converted outline in content/ if is_converted() is False: logging.print_info('Converted outline not found in ' + content_path) exit(0) global args import compile_book if len(args) == 1: output_format = str(args[0]) compile_book.compile_book_init(output_format) else: compile_book.compile_book_prompt() compile_book.compile_book()
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 build_template_prompt(): global book_name logging.print_info( 'What is a short name for your book project? This is not your title. [' + DEFAULT_BOOK_NAME + ']') book_name = str(input()) if not book_name: book_name = DEFAULT_BOOK_NAME book_name = cleanup_book_name(book_name)
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 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 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 build_template(): """ Executes actions build a new book template """ global args # Look for project in cwd if is_project_directory() is True: logging.print_info('Existing Tanagra project found in ' + cwd) exit(0) import build_template if len(args) == 1: book_name = str(args[0]) build_template.build_template_init(book_name) else: build_template.build_template_prompt() build_template.build_template()
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 convert_outline(): """ Executes actions to convert an outline to files in content directory """ # Look for project in cwd if is_project_directory() is False: logging.print_info('No Tanagra project found in ' + cwd) exit(0) # Look for converted outline in content/ if is_converted() is True: logging.print_info( 'Converted outline already found in content directory (' + content_path + '). Type "confirm" to overwrite content directory.') response = str(input()).lower() if response != "confirm": logging.print_info('Content directory overwrite not confirmed.') exit(1) # Convert outline import convert_outline convert_outline.convert_outline()
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 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 collect_tests(path='.'): print_info('Collecting tests...') all_filenames = get_filenames(path) tests = [] for filename in all_filenames: path_to_file = os.path.join(path, filename) if not is_python_source(filename): continue print_info('Searching at {}...'.format(filename)) commands = find_commands_at_file(path_to_file) if not len(commands): print_warning('No test commands for {}'.format(filename)) continue print_info('{} command was found:'.format(len(commands))) for current_command in commands: print_info('command: {}'.format(current_command)) tests.append(Test(path_to_file, current_command)) return tests
def build_template(): global book_name # create book directory book_path = cwd + '/' + book_name try: if not os.path.exists(book_path): os.makedirs(book_path) except OSError: sys.exit('Book directory "' + book_path + '" does not exist and cannot be created') # create content path content_path = book_path + '/content' try: # create content directory if not os.path.exists(content_path): os.makedirs(content_path) except OSError: sys.exit('Content directory "' + content_path + '" does not exist and cannot be created') # create output path output_path = book_path + '/output' try: # create content directory if not os.path.exists(output_path): os.makedirs(output_path) except OSError: sys.exit('Output directory "' + output_path + '" does not exist and cannot be created') # copy template files try: # copy outline.md shutil.copy(SCRIPT_PATH + '/templates/outline.md', book_path + '/outline.md') # copy metadata.md shutil.copy(SCRIPT_PATH + '/templates/metadata.md', book_path + '/metadata.md') # copy README files for allowing empty directories to be committed shutil.copy(SCRIPT_PATH + '/templates/README', content_path + '/README') shutil.copy(SCRIPT_PATH + '/templates/README', output_path + '/README') except OSError: sys.exit('Template file copy failed.') logging.print_info('Template creation completed.') logging.print_info(content_path) logging.print_info(output_path) logging.print_info(book_path + '/metadata.md') logging.print_info(book_path + '/outlne.md') print('\n') logging.print_info( 'Your book template is now ready. You may populate your metadata.md and outline.md files.' )
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")