def execute(): """ Main function. """ args = docopt_arguments() term = TerminalView() # print list of installed templates if args['--list']: run_list() return # instanciate the class if args['<template>']: template = template_class_from_name(args['<template>']) # print info on a template if args['--info']: if args['<template>']: run_info(template) else: term.print_error_and_exit("Please specify a template") return # launch the template template.create(args['<project>'], args['<template>'], args['<substitution>']) term.print_info("Done!")
def run_list(): """ Print the list of all available templates. """ term = TerminalView() term.print_info("These are the available templates:") import pkgutil, projy.templates pkgpath = os.path.dirname(projy.templates.__file__) templates = [name for _, name, _ in pkgutil.iter_modules([pkgpath])] for name in templates: # the father of all templates, not a real usable one if (name != 'ProjyTemplate'): term.print_info(term.text_in_color(template_name_from_class_name(name), TERM_PINK))
def template_class_from_name(name): """ Return the template class object from agiven name. """ # import the right template module term = TerminalView() template_name = name + 'Template' try: __import__('projy.templates.' + template_name) template_mod = sys.modules['projy.templates.' + template_name] except ImportError: term.print_error_and_exit("Unable to find {}".format(name)) # import the class from the module try: template_class = getattr(template_mod, template_name) except AttributeError: term.print_error_and_exit("Unable to create a template {}".format(name)) return template_class()
def run_info(template): """ Print information about a specific template. """ template.project_name = 'TowelStuff' # fake project name, always the same name = template_name_from_class_name(template.__class__.__name__) term = TerminalView() term.print_info("Content of template {} with an example project " \ "named 'TowelStuff':".format(term.text_in_color(name, TERM_GREEN))) dir_name = None for file_info in sorted(template.files(), key=lambda dir: dir[0]): directory = file_name = template_name = '' if file_info[0]: directory = file_info[0] if file_info[1]: file_name = file_info[1] if file_info[2]: template_name = '\t\t - ' + file_info[2] if (directory != dir_name): term.print_info('\n\t' + term.text_in_color(directory + '/', TERM_PINK)) dir_name = directory term.print_info('\t\t' + term.text_in_color(file_name, TERM_YELLOW) + template_name) # print substitutions try: subs = template.substitutes().keys() if len(subs) > 0: subs.sort() term.print_info("\nSubstitutions of this template are: ") max_len = 0 for key in subs: if max_len < len(key): max_len = len(key) for key in subs: term.print_info(u"\t{0:{1}} -> {2}". format(key, max_len, template.substitutes()[key])) except AttributeError: pass
def __init__(self): self.project_name = None self.template_name = None self.substitutes_dict = {} self.term = TerminalView()
class ProjyTemplate: """ Base template class for a Projy project creation. """ def __init__(self): self.project_name = None self.template_name = None self.substitutes_dict = {} self.term = TerminalView() def create(self, project_name, template_name, substitutions): """ Launch the project creation. """ self.project_name = project_name self.template_name = template_name # create substitutions dictionary from user arguments # TODO: check what is given for subs in substitutions: current_sub = subs.split(',') current_key = current_sub[0].strip() current_val = current_sub[1].strip() self.substitutes_dict[current_key] = current_val self.term.print_info(u"Creating project '{0}' with template {1}" .format(self.term.text_in_color(project_name, TERM_PINK), template_name)) self.make_directories() self.make_files() self.make_posthook() def make_directories(self): """ Create the directories of the template. """ # get the directories from the template directories = [] try: directories = self.directories() except AttributeError: self.term.print_info(u"No directory in the template.") working_dir = os.getcwd() # iteratively create the directories for directory in directories: dir_name = working_dir + '/' + directory if not os.path.isdir(dir_name): try: os.makedirs(dir_name) except OSError as error: if error.errno != errno.EEXIST: raise else: self.term.print_error_and_exit(u"The directory {0} already exists." .format(directory)) self.term.print_info(u"Creating directory '{0}'" .format(self.term.text_in_color(directory, TERM_GREEN))) def make_files(self): """ Create the files of the template. """ # get the files from the template files = [] try: files = self.files() except AttributeError: self.term.print_info(u"No file in the template. Weird, but why not?") # get the substitutes intersecting the template and the cli try: for key in self.substitutes().keys(): if key not in self.substitutes_dict: self.substitutes_dict[key] = self.substitutes()[key] except AttributeError: self.term.print_info(u"No substitute in the template.") working_dir = os.getcwd() # iteratively create the files for directory, name, template_file in files: if directory: filepath = working_dir + '/' + directory + '/' + name filename = directory + '/' + name else: filepath = working_dir + '/' + name filename = name # open the file to write into try: output = open(filepath, 'w') except IOError: self.term.print_error_and_exit(u"Can't create destination"\ " file: {0}".format(filepath)) # open the template to read from if template_file: input_file = join(dirname(__file__), template_file + '.txt') # write each line of input file into output file, # templatized with substitutes try: with open(input_file, 'r') as line: template_line = Template(line.read()) try: output.write(template_line. safe_substitute(self.substitutes_dict).encode('utf-8')) except TypeError: output.write(template_line. safe_substitute(self.substitutes_dict)) output.close() except IOError: self.term.print_error_and_exit(u"Can't create template file"\ ": {0}".format(input_file)) else: output.close() # the file is empty, but still created self.term.print_info(u"Creating file '{0}'" .format(self.term.text_in_color(filename, TERM_YELLOW))) def make_posthook(self): """ Run the post hook into the project directory. """ print(id(self.posthook), self.posthook) print(id(super(self.__class__, self).posthook), super(self.__class__, self).posthook) import ipdb;ipdb.set_trace() if self.posthook: os.chdir(self.project_name) # enter the project main directory self.posthook() def replace_in_file(self, file_path, old_exp, new_exp): """ In the given file, replace all 'old_exp' by 'new_exp'. """ self.term.print_info(u"Making replacement into {}" .format(self.term.text_in_color(file_path, TERM_GREEN))) # write the new version into a temporary file tmp_file = tempfile.NamedTemporaryFile(mode='w+t', delete=False) for filelineno, line in enumerate(io.open(file_path, encoding="utf-8")): if old_exp in line: line = line.replace(old_exp, new_exp) try: tmp_file.write(line.encode('utf-8')) except TypeError: tmp_file.write(line) name = tmp_file.name # keep the name tmp_file.close() shutil.copy(name, file_path) # replace the original one os.remove(name) def touch(self, filename): """ A simple equivalent of the well known shell 'touch' command. """ with file(filename, 'a'): os.utime(filename, None) def posthook(self): """ Empty post-hook, to be inherited. """ pass