def run(self): with CliReporter(self.env, verbosity=self.verbosity): self.build(update_source_info_first=True) for ts, eventtype, absolute_filename_w_path in self.watcher: DatabaseCache.purge_cache() if self.last_build is None or ts > self.last_build: self.build()
def build_cmd(ctx, output_path, watch, prune, verbosity, source_info_only, buildstate_path, profile, build_flags): """Builds the entire project into the final artifacts. The default behavior is to build the project into the default build output path which can be discovered with the `project-info` command but an alternative output folder can be provided with the `--output-path` option. The default behavior is to perform a build followed by a pruning step which removes no longer referenced artifacts from the output folder. Lektor will only build the files that require rebuilding if the output folder is reused. To enforce a clean build you have to issue a `clean` command first. If the build fails the exit code will be `1` otherwise `0`. This can be used by external scripts to only deploy on successful build for instance. """ from lektor.builder import Builder from lektor.reporter import CliReporter if output_path is None: output_path = ctx.get_default_output_path() ctx.load_plugins() env = ctx.get_env() def _build(): builder = Builder(env.new_pad(), output_path, buildstate_path=buildstate_path, build_flags=build_flags) if source_info_only: builder.update_all_source_infos() return True if profile: from .utils import profile_func failures = profile_func(builder.build_all) else: failures = builder.build_all() if prune: builder.prune() return failures == 0 reporter = CliReporter(env, verbosity=verbosity) with reporter: success = _build() if not watch: return sys.exit(0 if success else 1) from lektor.watcher import watch click.secho('Watching for file system changes', fg='cyan') last_build = time.time() for ts, _, _ in watch(env): if ts > last_build: _build() last_build = time.time()
def build_cmd(ctx, output_path, watch, prune, verbosity): """Builds the entire site out.""" from lektor.builder import Builder from lektor.reporter import CliReporter if output_path is None: output_path = ctx.get_default_output_path() env = ctx.get_env() def _build(): builder = Builder(ctx.new_pad(), output_path) builder.build_all() if prune: builder.prune() reporter = CliReporter(env, verbosity=verbosity) with reporter: _build() if not watch: return from lektor.watcher import watch click.secho('Watching for file system changes', fg='cyan') last_build = time.time() for ts, _, _ in watch(env): if ts > last_build: _build() last_build = time.time()
def __init__(self, *args, **kwargs): Plugin.__init__(self, *args, **kwargs) src_dir = self.env.root_path + '/' + (self.get_config().get('src_dir') or 'assets') + '/' target_dir = self.env.root_path + '/' + ( self.get_config().get('target_dir') or 'templates') + '/' self.observer = Observer() self.handler = HtmlHandler(target=target_dir) self.observer.schedule(self.handler, src_dir, recursive=True) cli_reporter = CliReporter(self.env) cli_reporter.report_generic( f'Starting webpack-html helper: {src_dir} -> {target_dir}') self.observer.start()
def run(self): with CliReporter(self.env, verbosity=self.verbosity): self.build(update_source_info_first=True) with Watcher(self.env, self.output_path) as watcher: for ts, _, _ in watcher: if self.last_build is None or ts > self.last_build: self.build()
def clean(self): from lektor.builder import Builder from lektor.reporter import CliReporter # self._ctx.load_plugins() env = self._ctx.get_env() reporter = CliReporter(env) # (env, verbosity=self._verbosity) with reporter: builder = Builder(env.new_pad(), self._dst) builder.prune(all=True)
def remove(ctx, relpath): lektor_cli_ctx = Context() lektor_cli_ctx.load_plugins() env = lektor_cli_ctx.get_env() path = os.path.join(OUTPUT_DIR, relpath) with CliReporter(env, verbosity=0), reporter.build('prune', None): if os.path.exists(path): reporter.report_pruned_artifact(relpath) if os.path.isdir(path): shutil.rmtree(path) else: os.remove(path)
def build(ctx): lektor_cli_ctx = Context() lektor_cli_ctx.load_plugins() env = lektor_cli_ctx.get_env() pad = env.new_pad() # This is essentially `lektor build --output-path build`. with CliReporter(env, verbosity=0): builder = Builder(pad, OUTPUT_DIR) failures = builder.build_all() if failures: raise invoke.Exit('Builder failed.')
def clean_cmd(ctx, output_path, verbosity): """Cleans the entire build folder.""" from lektor.builder import Builder from lektor.reporter import CliReporter if output_path is None: output_path = ctx.get_default_output_path() env = ctx.get_env() reporter = CliReporter(env, verbosity=verbosity) with reporter: builder = Builder(ctx.new_pad(), output_path) builder.prune(all=True)
def resolve_artifact(self, url_path, pad=None, redirect_slash=True): """Resolves an artifact and also triggers a build if necessary. Returns a tuple in the form ``(artifact_name, filename)`` where `artifact_name` can be `None` in case a file was targeted explicitly. """ if pad is None: pad = self.get_pad() artifact_name = filename = record_path = alt = None # We start with trying to resolve a source and then use the # primary source = pad.resolve_url_path(url_path) if source is not None: # If the request path does not end with a slash but we # requested a URL that actually wants a trailing slash, we # append it. This is consistent with what apache and nginx do # and it ensures our relative urls work. if ( not url_path.endswith("/") and source.url_path != "/" and source.url_path != url_path ): return abort(append_slash_redirect(request.environ)) with CliReporter(self.env, verbosity=self.verbosity): builder = self.get_builder(pad) prog, _ = builder.build(source) artifact = prog.primary_artifact if artifact is not None: artifact_name = artifact.artifact_name filename = artifact.dst_filename alt = source.alt if isinstance(source, Record): record_path = source.record.path if filename is None: path_list = url_path.strip("/").split("/") if sys.platform == "win32": filename = os.path.join(self.output_path, *path_list) else: filename = safe_join(self.output_path, *path_list) return ResolveResult(artifact_name, filename, record_path, alt)
def clean_cmd(ctx, output_path, verbosity): """Cleans the entire build folder. If not build folder is provided, the default build folder of the project in the Lektor cache is used. """ from lektor.builder import Builder from lektor.reporter import CliReporter if output_path is None: output_path = ctx.get_default_output_path() env = ctx.get_env() reporter = CliReporter(env, verbosity=verbosity) with reporter: builder = Builder(env.new_pad(), output_path) builder.prune(all=True)
def build(ctx, bust=False): lektor_cli_ctx = Context() if bust: project = lektor_cli_ctx.get_project() shutil.rmtree(project.get_package_cache_path(), ignore_errors=True) shutil.rmtree(project.get_output_path(), ignore_errors=True) lektor_cli_ctx.load_plugins() env = lektor_cli_ctx.get_env() pad = env.new_pad() # This is essentially `lektor build --output-path build`. with CliReporter(env, verbosity=0): builder = Builder(pad, OUTPUT_DIR) failures = builder.build_all() if failures: raise invoke.Exit('Builder failed.') # Generate redirect file. redirect_filename = os.path.join(OUTPUT_DIR, '_redirects') with io.open(redirect_filename, mode='w', encoding='utf8') as f: static_redirect = get_static_redirect() f.write(static_redirect) if not static_redirect.endswith('\n'): f.write('\n') f.write('\n') f.write('# Blog posts.\n') f.write('\n'.join(generate_blog_post_redirects(pad))) f.write('\n') f.write('\n') f.write('# Download redirects.\n') f.write('\n'.join(generate_download_redirects(pad))) f.write('\n') latest_redirect = get_latest_download_redirect(pad) if latest_redirect is not None: f.write('\n') f.write('# Latests version download links.\n') f.write(latest_redirect) f.write('\n')
def demo_output(site_path, my_plugin_id, my_plugin_cls, tmp_path_factory): """ Build the demo site. Return path to output directory. """ project = Project.from_path(str(site_path)) env = Environment(project, load_plugins=False) # Load our plugin env.plugin_controller.instanciate_plugin(my_plugin_id, my_plugin_cls) env.plugin_controller.emit('setup-env') pad = Database(env).new_pad() output_path = tmp_path_factory.mktemp('demo-site') builder = Builder(pad, str(output_path)) with CliReporter(env): failures = builder.build_all() assert failures == 0 return output_path
def build(self, tiny=False): from lektor.builder import Builder from lektor.reporter import CliReporter self._ctx.load_plugins() env = self._ctx.get_env() def _build(): builder = Builder(env.new_pad(), str(self._dst), buildstate_path=self._buildstate, extra_flags=self._buildflags if not tiny else []) failures = builder.build_all() builder.prune() return failures == 0 reporter = CliReporter(env, verbosity=True) with reporter: success = _build() return success
def demo_output(tmp_path_factory): """ Build the demo site. Return path to output director. """ site_dir = os.path.join(os.path.dirname(__file__), 'test-site') project = Project.from_path(site_dir) env = project.make_env(load_plugins=False) # Load our plugin env.plugin_controller.instanciate_plugin('polymorphic-type', PolymorphicTypePlugin) env.plugin_controller.emit('setup-env') output_path = tmp_path_factory.mktemp('output') builder = Builder(env.new_pad(), str(output_path)) with CliReporter(env): failures = builder.build_all() assert failures == 0 return output_path
def resolve_artifact(self, path, pad=None, redirect_slash=True): """Resolves an artifact and also triggers a build if necessary. Returns a tuple in the form ``(artifact_name, filename)`` where `artifact_name` can be `None` in case a file was targeted explicitly. """ if pad is None: pad = self.get_pad() artifact_name = filename = None # We start with trying to resolve a source and then use the # primary source = pad.resolve_url_path(path) if source is not None: # If the request path does not end with a slash but we # requested a URL that actually wants a trailing slash, we # append it. This is consistent with what apache and nginx do # and it ensures our relative urls work. if not path.endswith('/') and \ source.url_path != '/' and \ source.url_path != path: return abort(append_slash_redirect(request.environ)) with CliReporter(self.env, verbosity=self.verbosity): builder = self.get_builder(pad) prog, _ = builder.build(source) artifact = prog.primary_artifact if artifact is not None: artifact_name = artifact.artifact_name filename = artifact.dst_filename if filename is None: filename = safe_join(self.output_path, path.strip('/')) return artifact_name, filename
def handle_request(self, request): pad = self.get_pad() filename = None # We start with trying to resolve a source and then use the # primary source = pad.resolve_url_path(request.path) if source is not None: with CliReporter(self.env, verbosity=self.verbosity): builder = self.get_builder(pad) prog = builder.build(source) artifact = prog.primary_artifact if artifact is not None: filename = artifact.dst_filename # If there is no primary artifact or the url does not point to a # known artifact at all, then we just look directly into the # output directory and serve from there. This will for instance # pick up thumbnails. if filename is None: filename = os.path.join(self.output_path, request.path.strip('/')) return send_file(request, filename)
def run(self): with CliReporter(self.env, verbosity=self.verbosity): self.build(update_source_info_first=True) for ts, _, _ in self.watcher: if self.last_build is None or ts > self.last_build: self.build()
def run(self): with CliReporter(self.env, verbosity=self.verbosity): self.build() for ts, _, _ in self.watcher: if self.last_build is None or ts > self.last_build: self.build()