Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Pelican's invoke tasks.py #143

Merged
merged 4 commits into from
Apr 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,15 @@ Create a conda environment with pelican and the other needed dependencies::
$ conda env create -f env.yml
$ conda activate bikelab-website

Now you can build and serve the documentation with::
Now you can build and serve the documentation with this Make command (not
available on Windows by default)::

(bikelab-website)$ make devserver

or using Invoke (works on all operating systems)::

(bikelab-website)$ invoke livereload

If this succeeds you can open the website in your web browser at
http://localhost:8000.

Expand Down
2 changes: 2 additions & 0 deletions env.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,7 @@ channels:
dependencies:
- beautifulsoup4
- boto
- invoke
- livereload
- pelican
- pyyaml
92 changes: 0 additions & 92 deletions fabfile.py

This file was deleted.

147 changes: 147 additions & 0 deletions tasks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
import os
import shlex
import shutil
import sys
import datetime

from invoke import task
from invoke.main import program
from invoke.util import cd
from pelican import main as pelican_main
from pelican.server import ComplexHTTPRequestHandler, RootedHTTPServer
from pelican.settings import DEFAULT_CONFIG, get_settings_from_file

OPEN_BROWSER_ON_SERVE = True
SETTINGS_FILE_BASE = "pelicanconf.py"
SETTINGS = {}
SETTINGS.update(DEFAULT_CONFIG)
LOCAL_SETTINGS = get_settings_from_file(SETTINGS_FILE_BASE)
SETTINGS.update(LOCAL_SETTINGS)

CONFIG = {
"settings_base": SETTINGS_FILE_BASE,
"settings_publish": "publishconf.py",
# Output path. Can be absolute or relative to tasks.py. Default: 'output'
"deploy_path": SETTINGS["OUTPUT_PATH"],
# Host and port for `serve`
"host": "localhost",
"port": 8000,
}


@task
def clean(c):
"""Remove generated files"""
if os.path.isdir(CONFIG["deploy_path"]):
shutil.rmtree(CONFIG["deploy_path"])
os.makedirs(CONFIG["deploy_path"])


@task
def build(c):
"""Build local version of site"""
pelican_run("-s {settings_base}".format(**CONFIG))


@task
def rebuild(c):
"""`build` with the delete switch"""
pelican_run("-d -s {settings_base}".format(**CONFIG))


@task
def regenerate(c):
"""Automatically regenerate site upon file modification"""
pelican_run("-r -s {settings_base}".format(**CONFIG))


@task
def serve(c):
"""Serve site at http://$HOST:$PORT/ (default is localhost:8000)"""

class AddressReuseTCPServer(RootedHTTPServer):
allow_reuse_address = True

server = AddressReuseTCPServer(
CONFIG["deploy_path"],
(CONFIG["host"], CONFIG["port"]),
ComplexHTTPRequestHandler,
)

if OPEN_BROWSER_ON_SERVE:
# Open site in default browser
import webbrowser

webbrowser.open("http://{host}:{port}".format(**CONFIG))

sys.stderr.write("Serving at {host}:{port} ...\n".format(**CONFIG))
server.serve_forever()


@task
def reserve(c):
"""`build`, then `serve`"""
build(c)
serve(c)


@task
def preview(c):
"""Build production version of site"""
pelican_run("-s {settings_publish}".format(**CONFIG))

@task
def livereload(c):
"""Automatically reload browser tab upon file modification."""
from livereload import Server

def cached_build():
cmd = "-s {settings_base} -e CACHE_CONTENT=true LOAD_CONTENT_CACHE=true"
pelican_run(cmd.format(**CONFIG))

cached_build()
server = Server()
theme_path = SETTINGS["THEME"]
watched_globs = [
CONFIG["settings_base"],
f"{theme_path}/templates/**/*.html",
]

content_file_extensions = [".md", ".rst"]
for extension in content_file_extensions:
content_glob = "{}/**/*{}".format(SETTINGS["PATH"], extension)
watched_globs.append(content_glob)

static_file_extensions = [".css", ".js"]
for extension in static_file_extensions:
static_file_glob = f"{theme_path}/static/**/*{extension}"
watched_globs.append(static_file_glob)

for glob in watched_globs:
server.watch(glob, cached_build)

if OPEN_BROWSER_ON_SERVE:
# Open site in default browser
import webbrowser

webbrowser.open("http://{host}:{port}".format(**CONFIG))

server.serve(host=CONFIG["host"], port=CONFIG["port"], root=CONFIG["deploy_path"])


@task
def publish(c):
"""Publish to production via rsync"""
pelican_run("-s {settings_publish}".format(**CONFIG))
c.run(
'rsync --delete --exclude ".DS_Store" -pthrvz -c '
'-e "ssh -p {ssh_port}" '
"{} {ssh_user}@{ssh_host}:{ssh_path}".format(
CONFIG["deploy_path"].rstrip("/") + "/", **CONFIG
)
)


def pelican_run(cmd):
cmd += " " + program.core.remainder # allows to pass-through args to pelican
pelican_main(shlex.split(cmd))
Loading