tasks.py 4.0 KB

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