1
0
mirror of https://github.com/deadc0de6/dotdrop.git synced 2026-03-23 03:45:08 +00:00

adding ability to add custom functions and filters for #200

This commit is contained in:
deadc0de6
2020-01-12 12:01:03 +01:00
parent a7a8d92799
commit f02327c6e4
6 changed files with 304 additions and 13 deletions

View File

@@ -85,6 +85,7 @@ def cmd_install(o):
return False
t = Templategen(base=o.dotpath, variables=o.variables,
func_file=o.func_file, filter_file=o.filter_file,
debug=o.debug)
tmpdir = None
if o.install_temporary:
@@ -205,6 +206,7 @@ def cmd_compare(o, tmp):
return False
t = Templategen(base=o.dotpath, variables=o.variables,
func_file=o.func_file, filter_file=o.filter_file,
debug=o.debug)
inst = Installer(create=o.create, backup=o.backup,
dry=o.dry, base=o.dotpath,

View File

@@ -31,6 +31,8 @@ class Settings(DictParser):
key_instignore = 'instignore'
key_workdir = 'workdir'
key_minversion = 'minversion'
key_func_file = 'func_file'
key_filter_file = 'filter_file'
# import keys
key_import_actions = 'import_actions'
@@ -45,7 +47,7 @@ class Settings(DictParser):
link_on_import=LinkTypes.NOLINK, longkey=False,
upignore=[], cmpignore=[], instignore=[],
workdir='~/.config/dotdrop', showdiff=False,
minversion=None):
minversion=None, func_file=[], filter_file=[]):
self.backup = backup
self.banner = banner
self.create = create
@@ -65,6 +67,8 @@ class Settings(DictParser):
self.link_dotfile_default = LinkTypes.get(link_dotfile_default)
self.link_on_import = LinkTypes.get(link_on_import)
self.minversion = minversion
self.func_file = func_file
self.filter_file = filter_file
def _serialize_seq(self, name, dic):
"""serialize attribute 'name' into 'dic'"""
@@ -95,5 +99,7 @@ class Settings(DictParser):
self._serialize_seq(self.key_cmpignore, dic)
self._serialize_seq(self.key_upignore, dic)
self._serialize_seq(self.key_instignore, dic)
self._serialize_seq(self.key_func_file, dic)
self._serialize_seq(self.key_filter_file, dic)
return {self.key_yaml: dic}

View File

@@ -6,7 +6,6 @@ jinja2 template generator
"""
import os
import inspect
from jinja2 import Environment, FileSystemLoader
# local imports
@@ -24,10 +23,13 @@ COMMENT_END = '@@#}'
class Templategen:
def __init__(self, base='.', variables={}, debug=False):
def __init__(self, base='.', variables={},
func_file=[], filter_file=[], debug=False):
"""constructor
@base: directory path where to search for templates
@variables: dictionary of variables for templates
@func_file: file path to load functions from
@filter_file: file path to load filters from
@debug: enable debug
"""
self.base = base.rstrip(os.sep)
@@ -50,20 +52,22 @@ class Templategen:
# adding header method
self.env.globals['header'] = self._header
# adding helper methods
if self.debug:
self.log.dbg('load global functions:')
self._load_funcs_to_dic(jhelpers, self.env.globals)
if func_file:
for f in func_file:
if self.debug:
self.log.dbg('load custom functions from {}'.format(f))
self._load_path_to_dic(f, self.env.globals)
if filter_file:
for f in filter_file:
if self.debug:
self.log.dbg('load custom filters from {}'.format(f))
self._load_path_to_dic(f, self.env.filters)
if self.debug:
self.log.dbg('template additional variables: {}'.format(variables))
def _load_funcs_to_dic(self, mod, dic):
"""dynamically load functions from module to dic"""
for m in inspect.getmembers(mod):
name, func = m
if not inspect.isfunction(func):
continue
if self.debug:
self.log.dbg('load function \"{}\"'.format(name))
dic[name] = func
def generate(self, src):
"""render template from path"""
if not os.path.exists(src):
@@ -92,6 +96,23 @@ class Templategen:
"""update variables"""
self.env.globals.update(variables)
def _load_path_to_dic(self, path, dic):
mod = utils.get_module_from_path(path)
if not mod:
self.log.warn('cannot load module \"{}\"'.format(path))
return
self._load_funcs_to_dic(mod, dic)
def _load_funcs_to_dic(self, mod, dic):
"""dynamically load functions from module to dic"""
if not mod or not dic:
return
funcs = utils.get_module_functions(mod)
for name, func in funcs:
if self.debug:
self.log.dbg('load function \"{}\"'.format(name))
dic[name] = func
def _header(self, prepend=''):
"""add a comment usually in the header of a dotfile"""
return '{}{}'.format(prepend, utils.header())

View File

@@ -11,6 +11,8 @@ import os
import uuid
import shlex
import fnmatch
import inspect
import importlib
from shutil import rmtree
# local import
@@ -192,3 +194,24 @@ def patch_ignores(ignores, prefix, debug=False):
if debug:
LOG.dbg('ignores after patching: {}'.format(new))
return new
def get_module_functions(mod):
"""return a list of fonction from a module"""
funcs = []
for m in inspect.getmembers(mod):
name, func = m
if not inspect.isfunction(func):
continue
funcs.append((name, func))
return funcs
def get_module_from_path(path):
"""get module from path"""
if not path or not os.path.exists(path):
return None
module_name = os.path.basename(path).rstrip('.py')
loader = importlib.machinery.SourceFileLoader(module_name, path)
mod = loader.load_module()
return mod