tasks.py (3573B)
1 # -*- coding: utf-8 -*- 2 3 import os 4 import shlex 5 import shutil 6 import sys 7 import datetime 8 9 from invoke import task 10 from invoke.main import program 11 from invoke.util import cd 12 from pelican import main as pelican_main 13 from pelican.server import ComplexHTTPRequestHandler, RootedHTTPServer 14 from pelican.settings import DEFAULT_CONFIG, get_settings_from_file 15 16 SETTINGS_FILE_BASE = 'pelicanconf.py' 17 SETTINGS = {} 18 SETTINGS.update(DEFAULT_CONFIG) 19 LOCAL_SETTINGS = get_settings_from_file(SETTINGS_FILE_BASE) 20 SETTINGS.update(LOCAL_SETTINGS) 21 22 CONFIG = { 23 'settings_base': SETTINGS_FILE_BASE, 24 'settings_publish': 'publishconf.py', 25 # Output path. Can be absolute or relative to tasks.py. Default: 'output' 26 'deploy_path': SETTINGS['OUTPUT_PATH'], 27 # Host and port for `serve` 28 'host': 'localhost', 29 'port': 8000, 30 } 31 32 @task 33 def clean(c): 34 """Remove generated files""" 35 if os.path.isdir(CONFIG['deploy_path']): 36 shutil.rmtree(CONFIG['deploy_path']) 37 os.makedirs(CONFIG['deploy_path']) 38 39 @task 40 def build(c): 41 """Build local version of site""" 42 pelican_run('-s {settings_base}'.format(**CONFIG)) 43 44 @task 45 def rebuild(c): 46 """`build` with the delete switch""" 47 pelican_run('-d -s {settings_base}'.format(**CONFIG)) 48 49 @task 50 def regenerate(c): 51 """Automatically regenerate site upon file modification""" 52 pelican_run('-r -s {settings_base}'.format(**CONFIG)) 53 54 @task 55 def serve(c): 56 """Serve site at http://$HOST:$PORT/ (default is localhost:8000)""" 57 58 class AddressReuseTCPServer(RootedHTTPServer): 59 allow_reuse_address = True 60 61 server = AddressReuseTCPServer( 62 CONFIG['deploy_path'], 63 (CONFIG['host'], CONFIG['port']), 64 ComplexHTTPRequestHandler) 65 66 sys.stderr.write('Serving at {host}:{port} ...\n'.format(**CONFIG)) 67 server.serve_forever() 68 69 @task 70 def reserve(c): 71 """`build`, then `serve`""" 72 build(c) 73 serve(c) 74 75 @task 76 def preview(c): 77 """Build production version of site""" 78 pelican_run('-s {settings_publish}'.format(**CONFIG)) 79 80 @task 81 def livereload(c): 82 """Automatically reload browser tab upon file modification.""" 83 from livereload import Server 84 85 def cached_build(): 86 cmd = '-s {settings_base} -e CACHE_CONTENT=True LOAD_CONTENT_CACHE=True' 87 pelican_run(cmd.format(**CONFIG)) 88 89 cached_build() 90 server = Server() 91 theme_path = SETTINGS['THEME'] 92 watched_globs = [ 93 CONFIG['settings_base'], 94 '{}/templates/**/*.html'.format(theme_path), 95 ] 96 97 content_file_extensions = ['.md', '.rst'] 98 for extension in content_file_extensions: 99 content_glob = '{0}/**/*{1}'.format(SETTINGS['PATH'], extension) 100 watched_globs.append(content_glob) 101 102 static_file_extensions = ['.css', '.js'] 103 for extension in static_file_extensions: 104 static_file_glob = '{0}/static/**/*{1}'.format(theme_path, extension) 105 watched_globs.append(static_file_glob) 106 107 for glob in watched_globs: 108 server.watch(glob, cached_build) 109 server.serve(host=CONFIG['host'], port=CONFIG['port'], root=CONFIG['deploy_path']) 110 111 112 @task 113 def publish(c): 114 """Publish to production via rsync""" 115 pelican_run('-s {settings_publish}'.format(**CONFIG)) 116 c.run( 117 'rsync --delete --exclude ".DS_Store" -pthrvz -c ' 118 '-e "ssh -p {ssh_port}" ' 119 '{} {ssh_user}@{ssh_host}:{ssh_path}'.format( 120 CONFIG['deploy_path'].rstrip('/') + '/', 121 **CONFIG)) 122 123 124 def pelican_run(cmd): 125 cmd += ' ' + program.core.remainder # allows to pass-through args to pelican 126 pelican_main(shlex.split(cmd))