def get_path(src_root_, remaining_path, dst_root_, context_, prefix_len_): """return relative source path (to template dir) and destination path destination path is the absolute destination path """ src_path_ = (src_root_ + '/' + remaining_path)[prefix_len_:] dst_path_ = src_path_ if os.sep != '/': dst_path_ = dst_path_.replace('/', os.sep) dst_path_ = Template(dst_path_).render(**context_) if dst_path_.endswith('_tpl'): dst_path_ = dst_path_[:-4] return src_path_, os.path.join(dst_root_, dst_path_)
def expand_raw_value(self, raw_value, parents): """ Expand a string with placeholders Parameters ---------- raw_value : str The original value to expand parents : list The list of parents to get to this value in the dictionary Notes ----- If for a given raw_value, the first parent is 'path', expanded value is casted to pathlib.Path object and .expanduser() is called, furthermore, if raw_value ends with '/', a directory is created if it does not currently exist """ placeholders = util.get_tags_in_str(raw_value) if not placeholders: value = raw_value else: # get all required placeholders params = {k: self.load_placeholder(k) for k in placeholders} value = Template(raw_value).render(**params) if parents: if parents[0] == 'path': # value is a str (since it was loaded from a yaml file), # if it has an explicit trailing slash, interpret it as # a directory and create it, we have to do it at this point, # because once we cast to Path, we lose the trailing slash if value.endswith('/'): self._try_create_dir(value) return Path(value).expanduser() else: return cast_if_possible(value)
def copy_file_structure(rootdir, path, replace=None, files_to_ignore=None, partial=None, zipf=None, template_root=None, **kwargs): '''Walks through the file structure and copy all directories and files. Args: rootdir (str): the root directory where the files will be copied to path (str): the path to walk through and reproduce Keyword args: replace (dict, default=None): dictionary for file name replacement. Keys are old file names and values are new file names. files_to_ignore (list, default=None): list of file names to ignore. partial (list, default=None): list of paths for a partial build. Only the paths in the lists will be created. zipf (zipfile.ZipFile, default=None) template_root (str, default=None): the path to the project template directory **kwargs: dictionary containing the variables for templating ''' if not os.path.exists(rootdir) and zipf is None: raise IOError('Root directory not found: "'+rootdir+'"') if not files_to_ignore: files_to_ignore = get_config_param('files_to_ignore', []) if template_root is None: template_root = path for fname in os.listdir(path): src = os.path.join(path, fname) relpath = os.path.relpath(src, start=template_root) if partial and src not in partial: # Partial build: only files and dirs in the partial list # will be created continue ignoring = False for pat in files_to_ignore: if (fnmatch.fnmatch(fname, pat) or fnmatch.fnmatch(relpath, pat)): ignoring = True break if ignoring: # file path is in the list of files to ignore six.print_('File ignored: `{0}`'.format(src)) continue if replace and fname in replace: fname = Template(replace[fname]).render(**kwargs) elif fname.endswith('_py.template'): fname = fname[:-12]+'.py' dst = os.path.join(rootdir, fname) if os.path.isdir(src): if not os.path.exists(dst) and zipf is None: os.makedirs(dst) copy_file_structure(dst, src, replace=replace, partial=partial, files_to_ignore=files_to_ignore, zipf=zipf, template_root=template_root, **kwargs) elif os.path.isfile(src): file_content = render_template(src, **kwargs) create_general_file(dst, file_content, zipf=zipf)
def write_files(self, pypackage_name, dirname, context, destination_root, dry_run=False): """ write a full directory of template or plain files. Filenames can be templated too. pypackage_name is the Python package containing templates dirname is the directory name inside the Python package context is the Jinja2 context destination_root is the destination directory """ def get_path(src_root_, remaining_path, dst_root_, context_, prefix_len_): """return relative source path (to template dir) and destination path destination path is the absolute destination path """ src_path_ = (src_root_ + '/' + remaining_path)[prefix_len_:] dst_path_ = src_path_ if os.sep != '/': dst_path_ = dst_path_.replace('/', os.sep) dst_path_ = Template(dst_path_).render(**context_) if dst_path_.endswith('_tpl'): dst_path_ = dst_path_[:-4] return src_path_, os.path.join(dst_root_, dst_path_) def makedirs(path): if not dry_run: os.makedirs(path) valid(_('Directory %(f)s created.'), f=path) loader = PackageLoader(pypackage_name, dirname) env = Environment(loader=loader) env.filters['lower_first_letter'] = lower_first_letter destination_root = Template(destination_root).render(**context) if destination_root.endswith('_tpl'): destination_root = destination_root[:-4] if not os.path.isdir(destination_root): makedirs(destination_root) prefix_len = len(dirname) + 1 for root, dirnames, filenames in walk(pypackage_name, dirname): new_dirnames = [dirname for dirname in dirnames] for dirname in new_dirnames: if dirname in ('.svn', '.git', '.hg', 'CVS'): dirnames.remove(dirname) continue src_path, dst_path = get_path(root, dirname, destination_root, context, prefix_len) if not os.path.isdir(dst_path): makedirs(dst_path) for filename in filenames: if filename[-4:] == '_inc': continue src_path, dst_path = get_path(root, filename, destination_root, context, prefix_len) if self.dry_run: f_out = six.BytesIO() else: if not os.path.isdir(os.path.dirname(dst_path)): continue if os.path.isdir(dst_path): shutil.rmtree(dst_path) elif os.path.exists(dst_path): os.remove(dst_path) f_out = open(dst_path, 'wb') if filename[-4:] == '_tpl': template = env.get_template(src_path) f_out.write(template.render(**context).encode('utf-8')) else: f_in = pkg_resources.resource_stream(pypackage_name, root + '/' + filename) data = f_in.read(10240) while data: f_out.write(data) data = f_in.read(10240) f_in.close() f_out.close() valid(_('File %(f)s written.'), f=dst_path)