def __init__(self, project, load_plugins=True): self.project = project self.root_path = os.path.abspath(project.tree) self.jinja_env = CustomJinjaEnvironment( autoescape=self.select_jinja_autoescape, extensions=["jinja2.ext.autoescape", "jinja2.ext.with_"], loader=jinja2.FileSystemLoader(os.path.join(self.root_path, "templates")), ) from lektor.db import F self.jinja_env.filters.update( tojson=tojson_filter, latformat=lambda x, secs=True: format_lat_long(lat=x, secs=secs), longformat=lambda x, secs=True: format_lat_long(long=x, secs=secs), latlongformat=lambda x, secs=True: format_lat_long(secs=secs, *x), # By default filters need to be side-effect free. This is not # the case for this one, so we need to make it as a dummy # context filter so that jinja2 will not inline it. url=jinja2.contextfilter(lambda ctx, *a, **kw: url_to(*a, **kw)), asseturl=jinja2.contextfilter(lambda ctx, *a, **kw: get_asset_url(*a, **kw)), markdown=jinja2.contextfilter(lambda ctx, *a, **kw: Markdown(*a, **kw)), ) self.jinja_env.globals.update( F=F, url_to=url_to, site=site_proxy, config=config_proxy, bag=lookup_from_bag, get_random_id=lambda: uuid.uuid4().hex, ) self.jinja_env.filters.update( datetimeformat=_pass_locale(dates.format_datetime), dateformat=_pass_locale(dates.format_date), timeformat=_pass_locale(dates.format_time), ) from lektor.types import builtin_types self.types = builtin_types.copy() from lektor.publisher import builtin_publishers self.publishers = builtin_publishers.copy() # The plugins that are loaded for this environment. This is # modified by the plugin controller and registry methods on the # environment. self.plugin_controller = PluginController(self) self.plugins = {} self.plugin_ids_by_class = {} self.build_programs = [] self.special_file_assets = {} self.special_file_suffixes = {} self.custom_url_resolvers = [] self.custom_generators = [] if load_plugins: self.load_plugins()
def __init__(self, project): self.project = project self.root_path = os.path.abspath(project.tree) self.jinja_env = CustomJinjaEnvironment( autoescape=self.select_jinja_autoescape, extensions=['jinja2.ext.autoescape', 'jinja2.ext.with_'], loader=jinja2.FileSystemLoader( os.path.join(self.root_path, 'templates')) ) from lektor.db import F self.jinja_env.filters.update( tojson=tojson_filter, # By default filters need to be side-effect free. This is not # the case for this one, so we need to make it as a dummy # context filter so that jinja2 will not inline it. url=jinja2.contextfilter( lambda ctx, *a, **kw: url_to(*a, **kw)), asseturl=jinja2.contextfilter( lambda ctx, *a, **kw: url_to(get_asset_url(*a, **kw))), ) self.jinja_env.globals.update( F=F, url_to=url_to, site=site_proxy, config=config_proxy, bag=lookup_from_bag, get_random_id=lambda: uuid.uuid4().hex, ) from lektor.types import builtin_types self.types = builtin_types.copy() # The plugins that are loaded for this environment. This is # modified by the plugin controller and registry methods on the # environment. self.plugin_controller = PluginController(self) self.plugins = {} self.build_programs = [] self.special_file_assets = {} self.special_file_suffixes = {}
def __init__(self, project, load_plugins=True): self.project = project self.root_path = os.path.abspath(project.tree) self.theme_paths = [os.path.join(self.root_path, 'themes', theme) for theme in self.project.themes] if not self.theme_paths: # load the directories in the themes directory as the themes try: for fname in os.listdir(os.path.join(self.root_path, 'themes')): f = os.path.join(self.root_path, 'themes', fname) if os.path.isdir(f): self.theme_paths.append(f) except OSError: pass template_paths = [os.path.join(path, 'templates') for path in [self.root_path] + self.theme_paths] self.jinja_env = CustomJinjaEnvironment( autoescape=self.select_jinja_autoescape, extensions=['jinja2.ext.autoescape', 'jinja2.ext.with_'], loader=jinja2.FileSystemLoader( template_paths) ) from lektor.db import F, get_alts self.jinja_env.filters.update( tojson=tojson_filter, latformat=lambda x, secs=True: format_lat_long(lat=x, secs=secs), longformat=lambda x, secs=True: format_lat_long(long=x, secs=secs), latlongformat=lambda x, secs=True: format_lat_long(secs=secs, *x), # By default filters need to be side-effect free. This is not # the case for this one, so we need to make it as a dummy # context filter so that jinja2 will not inline it. url=jinja2.contextfilter( lambda ctx, *a, **kw: url_to(*a, **kw)), asseturl=jinja2.contextfilter( lambda ctx, *a, **kw: get_asset_url(*a, **kw)), markdown=jinja2.contextfilter( lambda ctx, *a, **kw: Markdown(*a, **kw)), ) self.jinja_env.globals.update( F=F, url_to=url_to, site=site_proxy, config=config_proxy, bag=lookup_from_bag, get_alts=get_alts, get_random_id=lambda: uuid.uuid4().hex, ) self.jinja_env.filters.update( datetimeformat=_pass_locale(dates.format_datetime), dateformat=_pass_locale(dates.format_date), timeformat=_pass_locale(dates.format_time), ) from lektor.types import builtin_types self.types = builtin_types.copy() from lektor.publisher import builtin_publishers self.publishers = builtin_publishers.copy() # The plugins that are loaded for this environment. This is # modified by the plugin controller and registry methods on the # environment. self.plugin_controller = PluginController(self) self.plugins = {} self.plugin_ids_by_class = {} self.build_programs = [] self.special_file_assets = {} self.special_file_suffixes = {} self.custom_url_resolvers = [] self.custom_generators = [] self.virtual_sources = {} if load_plugins: self.load_plugins() from lektor.db import siblings_resolver self.virtualpathresolver('siblings')(siblings_resolver)
class Environment(object): def __init__(self, project, load_plugins=True): self.project = project self.root_path = os.path.abspath(project.tree) self.theme_paths = [os.path.join(self.root_path, 'themes', theme) for theme in self.project.themes] if not self.theme_paths: # load the directories in the themes directory as the themes try: for fname in os.listdir(os.path.join(self.root_path, 'themes')): f = os.path.join(self.root_path, 'themes', fname) if os.path.isdir(f): self.theme_paths.append(f) except OSError: pass template_paths = [os.path.join(path, 'templates') for path in [self.root_path] + self.theme_paths] self.jinja_env = CustomJinjaEnvironment( autoescape=self.select_jinja_autoescape, extensions=['jinja2.ext.autoescape', 'jinja2.ext.with_'], loader=jinja2.FileSystemLoader( template_paths) ) from lektor.db import F, get_alts self.jinja_env.filters.update( tojson=tojson_filter, latformat=lambda x, secs=True: format_lat_long(lat=x, secs=secs), longformat=lambda x, secs=True: format_lat_long(long=x, secs=secs), latlongformat=lambda x, secs=True: format_lat_long(secs=secs, *x), # By default filters need to be side-effect free. This is not # the case for this one, so we need to make it as a dummy # context filter so that jinja2 will not inline it. url=jinja2.contextfilter( lambda ctx, *a, **kw: url_to(*a, **kw)), asseturl=jinja2.contextfilter( lambda ctx, *a, **kw: get_asset_url(*a, **kw)), markdown=jinja2.contextfilter( lambda ctx, *a, **kw: Markdown(*a, **kw)), ) self.jinja_env.globals.update( F=F, url_to=url_to, site=site_proxy, config=config_proxy, bag=lookup_from_bag, get_alts=get_alts, get_random_id=lambda: uuid.uuid4().hex, ) self.jinja_env.filters.update( datetimeformat=_pass_locale(dates.format_datetime), dateformat=_pass_locale(dates.format_date), timeformat=_pass_locale(dates.format_time), ) from lektor.types import builtin_types self.types = builtin_types.copy() from lektor.publisher import builtin_publishers self.publishers = builtin_publishers.copy() # The plugins that are loaded for this environment. This is # modified by the plugin controller and registry methods on the # environment. self.plugin_controller = PluginController(self) self.plugins = {} self.plugin_ids_by_class = {} self.build_programs = [] self.special_file_assets = {} self.special_file_suffixes = {} self.custom_url_resolvers = [] self.custom_generators = [] self.virtual_sources = {} if load_plugins: self.load_plugins() from lektor.db import siblings_resolver self.virtualpathresolver('siblings')(siblings_resolver) @property def asset_path(self): return os.path.join(self.root_path, 'assets') @property def temp_path(self): return os.path.join(self.root_path, 'temp') def load_plugins(self): """Loads the plugins.""" from .packages import load_packages from .pluginsystem import initialize_plugins load_packages(self) initialize_plugins(self) def load_config(self): """Loads the current config.""" return Config(self.project.project_file) def new_pad(self): """Convenience function to create a database and pad.""" from lektor.db import Database return Database(self).new_pad() def is_uninteresting_source_name(self, filename): """These files are ignored when sources are built into artifacts.""" fn = filename.lower() if fn in SPECIAL_ARTIFACTS: return False proj = self.project if any_fnmatch(filename, INCLUDED_ASSETS + proj.included_assets): # Included by the user's project config, thus not uninteresting. return False return any_fnmatch(filename, EXCLUDED_ASSETS + proj.excluded_assets) def is_ignored_artifact(self, asset_name): """This is used by the prune tool to figure out which files in the artifact folder should be ignored. """ fn = asset_name.lower() if fn in SPECIAL_ARTIFACTS: return False return fn[:1] == '.' or fn in IGNORED_FILES def render_template(self, name, pad=None, this=None, values=None, alt=None): ctx = self.make_default_tmpl_values(pad, this, values, alt, template=name) return self.jinja_env.get_or_select_template(name).render(ctx) def make_default_tmpl_values(self, pad=None, this=None, values=None, alt=None, template=None): values = dict(values or ()) # If not provided, pick the alt from the provided "this" object. # As there is no mandatory format for it, we make sure that we can # deal with a bad attribute there. if alt is None: if this is not None: alt = getattr(this, 'alt', None) if not isinstance(alt, string_types): alt = None if alt is None: alt = PRIMARY_ALT # This is already a global variable but we can inject it as a # local override if available. if pad is None: ctx = get_ctx() if ctx is not None: pad = ctx.pad if pad is not None: values['site'] = pad if this is not None: values['this'] = this if alt is not None: values['alt'] = alt self.plugin_controller.emit('process-template-context', context=values, template=template) return values def select_jinja_autoescape(self, filename): if filename is None: return False return filename.endswith(('.html', '.htm', '.xml', '.xhtml')) def resolve_custom_url_path(self, obj, url_path): for resolver in self.custom_url_resolvers: rv = resolver(obj, url_path) if rv is not None: return rv return None # -- methods for the plugin system def add_build_program(self, cls, program): self.build_programs.append((cls, program)) def add_asset_type(self, asset_cls, build_program): self.build_programs.append((asset_cls, build_program)) self.special_file_assets[asset_cls.source_extension] = asset_cls if asset_cls.artifact_extension: cext = asset_cls.source_extension + asset_cls.artifact_extension self.special_file_suffixes[cext] = asset_cls.source_extension def add_publisher(self, scheme, publisher): if scheme in self.publishers: raise RuntimeError('Scheme "%s" is already registered.' % scheme) self.publishers[scheme] = publisher def add_type(self, type): name = type.name if name in self.types: raise RuntimeError('Type "%s" is already registered.' % name) self.types[name] = type def virtualpathresolver(self, prefix): def decorator(func): if prefix in self.virtual_sources: raise RuntimeError('Prefix "%s" is already registered.' % prefix) self.virtual_sources[prefix] = func return func return decorator def urlresolver(self, func): self.custom_url_resolvers.append(func) return func def generator(self, func): self.custom_generators.append(func) return func
class Environment: def __init__(self, project, load_plugins=True, extra_flags=None): self.project = project self.root_path = os.path.abspath(project.tree) self.theme_paths = [ os.path.join(self.root_path, "themes", theme) for theme in self.project.themes ] if not self.theme_paths: # load the directories in the themes directory as the themes try: for fname in os.listdir(os.path.join(self.root_path, "themes")): f = os.path.join(self.root_path, "themes", fname) if os.path.isdir(f): self.theme_paths.append(f) except OSError: pass template_paths = [ os.path.join(path, "templates") for path in [self.root_path] + self.theme_paths ] self.jinja_env = CustomJinjaEnvironment( autoescape=self.select_jinja_autoescape, extensions=["jinja2.ext.autoescape", "jinja2.ext.with_", "jinja2.ext.do"], loader=jinja2.FileSystemLoader(template_paths), ) from lektor.db import F, get_alts # pylint: disable=import-outside-toplevel self.jinja_env.filters.update( tojson=tojson_filter, latformat=lambda x, secs=True: format_lat_long(lat=x, secs=secs), longformat=lambda x, secs=True: format_lat_long(long=x, secs=secs), latlongformat=lambda x, secs=True: format_lat_long(secs=secs, *x), # By default filters need to be side-effect free. This is not # the case for this one, so we need to make it as a dummy # context filter so that jinja2 will not inline it. url=jinja2.contextfilter(lambda ctx, *a, **kw: url_to(*a, **kw)), asseturl=jinja2.contextfilter( lambda ctx, *a, **kw: get_asset_url(*a, **kw) ), markdown=jinja2.contextfilter(lambda ctx, *a, **kw: Markdown(*a, **kw)), ) self.jinja_env.globals.update( F=F, url_to=url_to, site=site_proxy, config=config_proxy, bag=lookup_from_bag, get_alts=get_alts, get_random_id=lambda: uuid.uuid4().hex, ) self.jinja_env.filters.update( datetimeformat=_pass_locale(dates.format_datetime), dateformat=_pass_locale(dates.format_date), timeformat=_pass_locale(dates.format_time), ) self.types = builtin_types.copy() self.publishers = builtin_publishers.copy() # The plugins that are loaded for this environment. This is # modified by the plugin controller and registry methods on the # environment. self.plugin_controller = PluginController(self, extra_flags) self.plugins = {} self.plugin_ids_by_class = {} self.build_programs = [] self.special_file_assets = {} self.special_file_suffixes = {} self.custom_url_resolvers = [] self.custom_generators = [] self.virtual_sources = {} if load_plugins: self.load_plugins() # pylint: disable=import-outside-toplevel from lektor.db import siblings_resolver self.virtualpathresolver("siblings")(siblings_resolver) @property def asset_path(self): return os.path.join(self.root_path, "assets") @property def temp_path(self): return os.path.join(self.root_path, "temp") def load_plugins(self): """Loads the plugins.""" load_packages(self) initialize_plugins(self) def load_config(self): """Loads the current config.""" return Config(self.project.project_file) def new_pad(self): """Convenience function to create a database and pad.""" from lektor.db import Database # pylint: disable=import-outside-toplevel return Database(self).new_pad() def is_uninteresting_source_name(self, filename): """These files are ignored when sources are built into artifacts.""" fn = filename.lower() if fn in SPECIAL_ARTIFACTS: return False proj = self.project if any_fnmatch(filename, INCLUDED_ASSETS + proj.included_assets): # Included by the user's project config, thus not uninteresting. return False return any_fnmatch(filename, EXCLUDED_ASSETS + proj.excluded_assets) @staticmethod def is_ignored_artifact(asset_name): """This is used by the prune tool to figure out which files in the artifact folder should be ignored. """ fn = asset_name.lower() if fn in SPECIAL_ARTIFACTS: return False return fn[:1] == "." or fn in IGNORED_FILES def render_template(self, name, pad=None, this=None, values=None, alt=None): ctx = self.make_default_tmpl_values(pad, this, values, alt, template=name) return self.jinja_env.get_or_select_template(name).render(ctx) def make_default_tmpl_values( self, pad=None, this=None, values=None, alt=None, template=None ): values = dict(values or ()) # If not provided, pick the alt from the provided "this" object. # As there is no mandatory format for it, we make sure that we can # deal with a bad attribute there. if alt is None: if this is not None: alt = getattr(this, "alt", None) if not isinstance(alt, str): alt = None if alt is None: alt = PRIMARY_ALT # This is already a global variable but we can inject it as a # local override if available. if pad is None: ctx = get_ctx() if ctx is not None: pad = ctx.pad if pad is not None: values["site"] = pad if this is not None: values["this"] = this if alt is not None: values["alt"] = alt self.plugin_controller.emit( "process-template-context", context=values, template=template ) return values @staticmethod def select_jinja_autoescape(filename): if filename is None: return False return filename.endswith((".html", ".htm", ".xml", ".xhtml")) def resolve_custom_url_path(self, obj, url_path): for resolver in self.custom_url_resolvers: rv = resolver(obj, url_path) if rv is not None: return rv return None # -- methods for the plugin system def add_build_program(self, cls, program): self.build_programs.append((cls, program)) def add_asset_type(self, asset_cls, build_program): self.build_programs.append((asset_cls, build_program)) self.special_file_assets[asset_cls.source_extension] = asset_cls if asset_cls.artifact_extension: cext = asset_cls.source_extension + asset_cls.artifact_extension self.special_file_suffixes[cext] = asset_cls.source_extension def add_publisher(self, scheme, publisher): if scheme in self.publishers: raise RuntimeError('Scheme "%s" is already registered.' % scheme) self.publishers[scheme] = publisher def add_type(self, type): name = type.name if name in self.types: raise RuntimeError('Type "%s" is already registered.' % name) self.types[name] = type def virtualpathresolver(self, prefix): def decorator(func): if prefix in self.virtual_sources: raise RuntimeError('Prefix "%s" is already registered.' % prefix) self.virtual_sources[prefix] = func return func return decorator def urlresolver(self, func): self.custom_url_resolvers.append(func) return func def generator(self, func): self.custom_generators.append(func) return func
def __init__(self, project, load_plugins=True, extra_flags=None): self.project = project self.root_path = os.path.abspath(project.tree) self.theme_paths = [ os.path.join(self.root_path, "themes", theme) for theme in self.project.themes ] if not self.theme_paths: # load the directories in the themes directory as the themes try: for fname in os.listdir(os.path.join(self.root_path, "themes")): f = os.path.join(self.root_path, "themes", fname) if os.path.isdir(f): self.theme_paths.append(f) except OSError: pass template_paths = [ os.path.join(path, "templates") for path in [self.root_path] + self.theme_paths ] self.jinja_env = CustomJinjaEnvironment( autoescape=self.select_jinja_autoescape, extensions=["jinja2.ext.autoescape", "jinja2.ext.with_", "jinja2.ext.do"], loader=jinja2.FileSystemLoader(template_paths), ) from lektor.db import F, get_alts self.jinja_env.filters.update( tojson=tojson_filter, latformat=lambda x, secs=True: format_lat_long(lat=x, secs=secs), longformat=lambda x, secs=True: format_lat_long(long=x, secs=secs), latlongformat=lambda x, secs=True: format_lat_long(secs=secs, *x), # By default filters need to be side-effect free. This is not # the case for this one, so we need to make it as a dummy # context filter so that jinja2 will not inline it. url=jinja2.contextfilter(lambda ctx, *a, **kw: url_to(*a, **kw)), asseturl=jinja2.contextfilter( lambda ctx, *a, **kw: get_asset_url(*a, **kw) ), markdown=jinja2.contextfilter(lambda ctx, *a, **kw: Markdown(*a, **kw)), ) self.jinja_env.globals.update( F=F, url_to=url_to, site=site_proxy, config=config_proxy, bag=lookup_from_bag, get_alts=get_alts, get_random_id=lambda: uuid.uuid4().hex, ) self.jinja_env.filters.update( datetimeformat=_pass_locale(dates.format_datetime), dateformat=_pass_locale(dates.format_date), timeformat=_pass_locale(dates.format_time), ) from lektor.types import builtin_types self.types = builtin_types.copy() from lektor.publisher import builtin_publishers self.publishers = builtin_publishers.copy() # The plugins that are loaded for this environment. This is # modified by the plugin controller and registry methods on the # environment. self.plugin_controller = PluginController(self, extra_flags) self.plugins = {} self.plugin_ids_by_class = {} self.build_programs = [] self.special_file_assets = {} self.special_file_suffixes = {} self.custom_url_resolvers = [] self.custom_generators = [] self.virtual_sources = {} if load_plugins: self.load_plugins() from lektor.db import siblings_resolver self.virtualpathresolver("siblings")(siblings_resolver)
def __init__(self, project, load_plugins=True): self.project = project self.root_path = os.path.abspath(project.tree) self.jinja_env = CustomJinjaEnvironment( autoescape=self.select_jinja_autoescape, extensions=['jinja2.ext.autoescape', 'jinja2.ext.with_'], loader=jinja2.FileSystemLoader( os.path.join(self.root_path, 'templates')) ) from lektor.db import F self.jinja_env.filters.update( tojson=tojson_filter, latformat=lambda x, secs=True: format_lat_long(lat=x, secs=secs), longformat=lambda x, secs=True: format_lat_long(long=x, secs=secs), latlongformat=lambda x, secs=True: format_lat_long(secs=secs, *x), # By default filters need to be side-effect free. This is not # the case for this one, so we need to make it as a dummy # context filter so that jinja2 will not inline it. url=jinja2.contextfilter( lambda ctx, *a, **kw: url_to(*a, **kw)), asseturl=jinja2.contextfilter( lambda ctx, *a, **kw: get_asset_url(*a, **kw)), markdown=jinja2.contextfilter( lambda ctx, *a, **kw: Markdown(*a, **kw)), ) self.jinja_env.globals.update( F=F, url_to=url_to, site=site_proxy, config=config_proxy, bag=lookup_from_bag, get_random_id=lambda: uuid.uuid4().hex, ) self.jinja_env.filters.update( datetimeformat=_pass_locale(dates.format_datetime), dateformat=_pass_locale(dates.format_date), timeformat=_pass_locale(dates.format_time), ) from lektor.types import builtin_types self.types = builtin_types.copy() from lektor.publisher import builtin_publishers self.publishers = builtin_publishers.copy() # The plugins that are loaded for this environment. This is # modified by the plugin controller and registry methods on the # environment. self.plugin_controller = PluginController(self) self.plugins = {} self.plugin_ids_by_class = {} self.build_programs = [] self.special_file_assets = {} self.special_file_suffixes = {} self.custom_url_resolvers = [] self.custom_generators = [] if load_plugins: self.load_plugins()
class Environment(object): def __init__(self, project, load_plugins=True): self.project = project self.root_path = os.path.abspath(project.tree) self.jinja_env = CustomJinjaEnvironment( autoescape=self.select_jinja_autoescape, extensions=['jinja2.ext.autoescape', 'jinja2.ext.with_'], loader=jinja2.FileSystemLoader( os.path.join(self.root_path, 'templates')) ) from lektor.db import F self.jinja_env.filters.update( tojson=tojson_filter, latformat=lambda x, secs=True: format_lat_long(lat=x, secs=secs), longformat=lambda x, secs=True: format_lat_long(long=x, secs=secs), latlongformat=lambda x, secs=True: format_lat_long(secs=secs, *x), # By default filters need to be side-effect free. This is not # the case for this one, so we need to make it as a dummy # context filter so that jinja2 will not inline it. url=jinja2.contextfilter( lambda ctx, *a, **kw: url_to(*a, **kw)), asseturl=jinja2.contextfilter( lambda ctx, *a, **kw: get_asset_url(*a, **kw)), markdown=jinja2.contextfilter( lambda ctx, *a, **kw: Markdown(*a, **kw)), ) self.jinja_env.globals.update( F=F, url_to=url_to, site=site_proxy, config=config_proxy, bag=lookup_from_bag, get_random_id=lambda: uuid.uuid4().hex, ) self.jinja_env.filters.update( datetimeformat=_pass_locale(dates.format_datetime), dateformat=_pass_locale(dates.format_date), timeformat=_pass_locale(dates.format_time), ) from lektor.types import builtin_types self.types = builtin_types.copy() from lektor.publisher import builtin_publishers self.publishers = builtin_publishers.copy() # The plugins that are loaded for this environment. This is # modified by the plugin controller and registry methods on the # environment. self.plugin_controller = PluginController(self) self.plugins = {} self.plugin_ids_by_class = {} self.build_programs = [] self.special_file_assets = {} self.special_file_suffixes = {} self.custom_url_resolvers = [] self.custom_generators = [] if load_plugins: self.load_plugins() @property def asset_path(self): return os.path.join(self.root_path, 'assets') @property def temp_path(self): return os.path.join(self.root_path, 'temp') def load_plugins(self): """Loads the plugins.""" from .packages import load_packages from .pluginsystem import initialize_plugins load_packages(self) initialize_plugins(self) def load_config(self): """Loads the current config.""" return Config(self.project.project_file) def new_pad(self): """Convenience function to create a database and pad.""" from lektor.db import Database return Database(self).new_pad() def is_uninteresting_source_name(self, filename): """These files are always ignored when sources are built into artifacts. """ fn = filename.lower() if fn in SPECIAL_ARTIFACTS: return False return filename[:1] in '._' or fn in IGNORED_FILES def is_ignored_artifact(self, asset_name): """This is used by the prune tool to figure out which files in the artifact folder should be ignored. """ fn = asset_name.lower() if fn in SPECIAL_ARTIFACTS: return False return fn[:1] == '.' or fn in IGNORED_FILES def render_template(self, name, pad=None, this=None, values=None, alt=None): ctx = self.make_default_tmpl_values(pad, this, values, alt, template=name) return self.jinja_env.get_or_select_template(name).render(ctx) def make_default_tmpl_values(self, pad=None, this=None, values=None, alt=None, template=None): values = dict(values or ()) # If not provided, pick the alt from the provided "this" object. # As there is no mandatory format for it, we make sure that we can # deal with a bad attribute there. if alt is None: if this is not None: alt = getattr(this, 'alt', None) if not isinstance(alt, basestring): alt = None if alt is None: alt = PRIMARY_ALT # This is already a global variable but we can inject it as a # local override if available. if pad is None: ctx = get_ctx() if ctx is not None: pad = ctx.pad if pad is not None: values['site'] = pad if this is not None: values['this'] = this if alt is not None: values['alt'] = alt self.plugin_controller.emit('process-template-context', context=values, template=template) return values def select_jinja_autoescape(self, filename): if filename is None: return False return filename.endswith(('.html', '.htm', '.xml', '.xhtml')) def resolve_custom_url_path(self, obj, url_path): for resolver in self.custom_url_resolvers: rv = resolver(obj, url_path) if rv is not None: return rv # -- methods for the plugin system def add_build_program(self, cls, program): self.build_programs.append((cls, program)) def add_asset_type(self, asset_cls, build_program): self.build_programs.append((asset_cls, build_program)) self.special_file_assets[asset_cls.source_extension] = asset_cls if asset_cls.artifact_extension: cext = asset_cls.source_extension + asset_cls.artifact_extension self.special_file_suffixes[cext] = asset_cls.source_extension def add_publisher(self, scheme, publisher): if scheme in self.publishers: raise RuntimeError('Scheme "%s" is already registered.' % scheme) self.publishers[scheme] = publisher def urlresolver(self, func): self.custom_url_resolvers.append(func) return func def generator(self, func): self.custom_generators.append(func) return func
def test_env_went_away(self): env = mock.Mock(name="env", spec=()) plugin_controller = PluginController(env) del env with pytest.raises(RuntimeError, match=r"Environment went away"): getattr(plugin_controller, "env")
def plugin_controller(self, env, extra_flags): return PluginController(env, extra_flags)
class Environment(object): def __init__(self, project): self.project = project self.root_path = os.path.abspath(project.tree) self.jinja_env = CustomJinjaEnvironment( autoescape=self.select_jinja_autoescape, extensions=['jinja2.ext.autoescape', 'jinja2.ext.with_'], loader=jinja2.FileSystemLoader( os.path.join(self.root_path, 'templates')) ) from lektor.db import F self.jinja_env.filters.update( tojson=tojson_filter, # By default filters need to be side-effect free. This is not # the case for this one, so we need to make it as a dummy # context filter so that jinja2 will not inline it. url=jinja2.contextfilter( lambda ctx, *a, **kw: url_to(*a, **kw)), asseturl=jinja2.contextfilter( lambda ctx, *a, **kw: url_to(get_asset_url(*a, **kw))), ) self.jinja_env.globals.update( F=F, url_to=url_to, site=site_proxy, config=config_proxy, bag=lookup_from_bag, get_random_id=lambda: uuid.uuid4().hex, ) from lektor.types import builtin_types self.types = builtin_types.copy() # The plugins that are loaded for this environment. This is # modified by the plugin controller and registry methods on the # environment. self.plugin_controller = PluginController(self) self.plugins = {} self.build_programs = [] self.special_file_assets = {} self.special_file_suffixes = {} @property def asset_path(self): return os.path.join(self.root_path, 'assets') @property def temp_path(self): return os.path.join(self.root_path, 'temp') def load_config(self): """Loads the current config.""" return Config(self.project.project_file) def is_uninteresting_source_name(self, filename): """These files are always ignored when sources are built into artifacts. """ fn = filename.lower() if fn in SPECIAL_ARTIFACTS or fn in SPECIAL_SOURCES: return False return filename[:1] in '._' or fn in IGNORED_FILES def is_ignored_artifact(self, asset_name): """This is used by the prune tool to figure out which files in the artifact folder should be ignored. This is a bi """ fn = asset_name.lower() if fn in SPECIAL_ARTIFACTS: return False return fn[:1] in '._' or fn in IGNORED_FILES def render_template(self, name, pad=None, this=None, values=None, alt=None): ctx = self.make_default_tmpl_values(pad, this, values, alt) return self.jinja_env.get_or_select_template(name).render(ctx) def make_default_tmpl_values(self, pad=None, this=None, values=None, alt=None): values = dict(values or ()) # If not provided, pick the alt from the provided "this" object. # As there is no mandatory format for it, we make sure that we can # deal with a bad attribute there. if alt is None: if this is not None: alt = getattr(this, 'alt', None) if not isinstance(alt, basestring): alt = None if alt is None: alt = PRIMARY_ALT # This is already a global variable but we can inject it as a # local override if available. if pad is None: ctx = get_ctx() if ctx is not None: pad = ctx.pad if pad is not None: values['site'] = pad if this is not None: values['this'] = this if alt is not None: values['alt'] = alt self.plugin_controller.emit('process_template_context', context=values) return values def select_jinja_autoescape(self, filename): if filename is None: return False return filename.endswith(('.html', '.htm', '.xml', '.xhtml')) # -- methods for the plugin system def add_asset_type(self, asset_cls, build_program): self.build_programs.append((asset_cls, build_program)) self.special_file_assets[asset_cls.source_extension] = asset_cls if asset_cls.artifact_extension: cext = asset_cls.source_extension + asset_cls.artifact_extension self.special_file_suffixes[cext] = asset_cls.source_extension