diff --git a/pelican/tools/pelican_quickstart.py b/pelican/tools/pelican_quickstart.py index a03f52df..1d136a0a 100755 --- a/pelican/tools/pelican_quickstart.py +++ b/pelican/tools/pelican_quickstart.py @@ -6,9 +6,10 @@ import argparse import codecs import locale import os -import string import sys +from jinja2 import Environment, FileSystemLoader + import pytz try: @@ -30,6 +31,11 @@ else: _TEMPLATES_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "templates") +_jinja_env = Environment( + loader=FileSystemLoader(_TEMPLATES_DIR), + trim_blocks=True, +) + _GITHUB_PAGES_BRANCHES = { 'personal': 'master', @@ -99,20 +105,6 @@ def decoding_strings(f): return wrapper -def get_template(name, as_encoding='utf-8'): - template = os.path.join(_TEMPLATES_DIR, "{0}.in".format(name)) - - if not os.path.isfile(template): - raise RuntimeError("Cannot open {0}".format(template)) - - with codecs.open(template, 'r', as_encoding) as fd: - line = fd.readline() - while line: - yield line - line = fd.readline() - fd.close() - - @decoding_strings def ask(question, answer=str_compat, default=None, length=None): if answer == str_compat: @@ -273,6 +265,7 @@ needed by Pelican. if automation: if ask('Do you want to upload your website using FTP?', answer=bool, default=False): + CONF['ftp'] = True, CONF['ftp_host'] = ask('What is the hostname of your FTP server?', str_compat, CONF['ftp_host']) CONF['ftp_user'] = ask('What is your username on that server?', @@ -282,6 +275,7 @@ needed by Pelican. str_compat, CONF['ftp_target_dir']) if ask('Do you want to upload your website using SSH?', answer=bool, default=False): + CONF['ssh'] = True, CONF['ssh_host'] = ask('What is the hostname of your SSH server?', str_compat, CONF['ssh_host']) CONF['ssh_port'] = ask('What is the port of your SSH server?', @@ -294,16 +288,19 @@ needed by Pelican. if ask('Do you want to upload your website using Dropbox?', answer=bool, default=False): + CONF['dropbox'] = True, CONF['dropbox_dir'] = ask('Where is your Dropbox directory?', str_compat, CONF['dropbox_dir']) if ask('Do you want to upload your website using S3?', answer=bool, default=False): + CONF['s3'] = True, CONF['s3_bucket'] = ask('What is the name of your S3 bucket?', str_compat, CONF['s3_bucket']) if ask('Do you want to upload your website using ' 'Rackspace Cloud Files?', answer=bool, default=False): + CONF['cloudfiles'] = True, CONF['cloudfiles_username'] = ask('What is your Rackspace ' 'Cloud username?', str_compat, CONF['cloudfiles_username']) @@ -317,6 +314,7 @@ needed by Pelican. if ask('Do you want to upload your website using GitHub Pages?', answer=bool, default=False): + CONF['github'] = True, if ask('Is this your personal page (username.github.io)?', answer=bool, default=False): CONF['github_pages_branch'] = \ @@ -342,9 +340,8 @@ needed by Pelican. for key, value in CONF.items(): conf_python[key] = repr(value) - for line in get_template('pelicanconf.py'): - template = string.Template(line) - fd.write(template.safe_substitute(conf_python)) + _template = _jinja_env.get_template('pelicanconf.py.jinja2') + fd.write(_template.render(**conf_python)) fd.close() except OSError as e: print('Error: {0}'.format(e)) @@ -352,9 +349,8 @@ needed by Pelican. try: with codecs.open(os.path.join(CONF['basedir'], 'publishconf.py'), 'w', 'utf-8') as fd: - for line in get_template('publishconf.py'): - template = string.Template(line) - fd.write(template.safe_substitute(CONF)) + _template = _jinja_env.get_template('publishconf.py.jinja2') + fd.write(_template.render(**CONF)) fd.close() except OSError as e: print('Error: {0}'.format(e)) @@ -363,25 +359,19 @@ needed by Pelican. try: with codecs.open(os.path.join(CONF['basedir'], 'fabfile.py'), 'w', 'utf-8') as fd: - for line in get_template('fabfile.py'): - template = string.Template(line) - fd.write(template.safe_substitute(CONF)) + _template = _jinja_env.get_template('fabfile.py.jinja2') + fd.write(_template.render(**CONF)) fd.close() except OSError as e: print('Error: {0}'.format(e)) try: with codecs.open(os.path.join(CONF['basedir'], 'Makefile'), 'w', 'utf-8') as fd: - mkfile_template_name = 'Makefile' - py_v = 'PY?=python' + py_v = 'python' if six.PY3: - py_v = 'PY?=python3' - template = string.Template(py_v) - fd.write(template.safe_substitute(CONF)) - fd.write('\n') - for line in get_template(mkfile_template_name): - template = string.Template(line) - fd.write(template.safe_substitute(CONF)) + py_v = 'python3' + _template = _jinja_env.get_template('Makefile.jinja2') + fd.write(_template.render(py_v=py_v, **CONF)) fd.close() except OSError as e: print('Error: {0}'.format(e)) @@ -396,14 +386,11 @@ needed by Pelican. with codecs.open(os.path.join(CONF['basedir'], 'develop_server.sh'), 'w', 'utf-8') as fd: - lines = list(get_template('develop_server.sh')) - py_v = 'PY=${PY:-python}\n' + py_v = '${PY:-python}' if six.PY3: - py_v = 'PY=${PY:-python3}\n' - lines = lines[:4] + [py_v] + lines[4:] - for line in lines: - template = string.Template(line) - fd.write(template.safe_substitute(conf_shell)) + py_v = '${PY:-python3}' + _template = _jinja_env.get_template('develop_server.sh.jinja2') + fd.write(_template.render(py_v=py_v, **conf_shell)) fd.close() # mode 0o755 diff --git a/pelican/tools/templates/Makefile.in b/pelican/tools/templates/Makefile.jinja2 similarity index 56% rename from pelican/tools/templates/Makefile.in rename to pelican/tools/templates/Makefile.jinja2 index 5dc81baa..42424cdd 100644 --- a/pelican/tools/templates/Makefile.in +++ b/pelican/tools/templates/Makefile.jinja2 @@ -1,30 +1,44 @@ -PELICAN?=$pelican -PELICANOPTS=$pelicanopts +PY?={{py_v}} +PELICAN?={{pelican}} +PELICANOPTS={{pelicanopts}} -BASEDIR=$$(CURDIR) -INPUTDIR=$$(BASEDIR)/content -OUTPUTDIR=$$(BASEDIR)/output -CONFFILE=$$(BASEDIR)/pelicanconf.py -PUBLISHCONF=$$(BASEDIR)/publishconf.py +BASEDIR=$(CURDIR) +INPUTDIR=$(BASEDIR)/content +OUTPUTDIR=$(BASEDIR)/output +CONFFILE=$(BASEDIR)/pelicanconf.py +PUBLISHCONF=$(BASEDIR)/publishconf.py -FTP_HOST=$ftp_host -FTP_USER=$ftp_user -FTP_TARGET_DIR=$ftp_target_dir +{% if ftp %} +FTP_HOST={{ftp_host}} +FTP_USER={{ftp_user}} +FTP_TARGET_DIR={{ftp_target_dir}} -SSH_HOST=$ssh_host -SSH_PORT=$ssh_port -SSH_USER=$ssh_user -SSH_TARGET_DIR=$ssh_target_dir +{% endif %} +{% if ssh %} +SSH_HOST={{ssh_host}} +SSH_PORT={{ssh_port}} +SSH_USER={{ssh_user}} +SSH_TARGET_DIR={{ssh_target_dir}} -S3_BUCKET=$s3_bucket +{% endif %} +{% if s3 %} +S3_BUCKET={{s3_bucket}} -CLOUDFILES_USERNAME=$cloudfiles_username -CLOUDFILES_API_KEY=$cloudfiles_api_key -CLOUDFILES_CONTAINER=$cloudfiles_container +{% endif %} +{% if cloudfiles %} +CLOUDFILES_USERNAME={{cloudfiles_username}} +CLOUDFILES_API_KEY={{cloudfiles_api_key}} +CLOUDFILES_CONTAINER={{cloudfiles_container}} -DROPBOX_DIR=$dropbox_dir +{% endif %} +{% if dropbox %} +DROPBOX_DIR={{dropbox_dir}} -GITHUB_PAGES_BRANCH=$github_pages_branch +{% endif %} +{% if github %} +GITHUB_PAGES_BRANCH={{github_pages_branch}} + +{% endif %} DEBUG ?= 0 ifeq ($(DEBUG), 1) @@ -48,47 +62,59 @@ help: @echo ' make serve-global [SERVER=0.0.0.0] serve (as root) to $(SERVER):80 ' @echo ' make devserver [PORT=8000] start/restart develop_server.sh ' @echo ' make stopserver stop local server ' +{% if ssh %} @echo ' make ssh_upload upload the web site via SSH ' @echo ' make rsync_upload upload the web site via rsync+ssh ' +{% endif %} +{% if dropbox %} @echo ' make dropbox_upload upload the web site via Dropbox ' +{% endif %} +{% if ftp %} @echo ' make ftp_upload upload the web site via FTP ' +{% endif %} +{% if s3 %} @echo ' make s3_upload upload the web site via S3 ' +{% endif %} +{% if cloudfiles %} @echo ' make cf_upload upload the web site via Cloud Files' +{% endif %} +{% if github %} @echo ' make github upload the web site via gh-pages ' +{% endif %} @echo ' ' @echo 'Set the DEBUG variable to 1 to enable debugging, e.g. make DEBUG=1 html ' @echo 'Set the RELATIVE variable to 1 to enable relative urls ' @echo ' ' html: - $$(PELICAN) $$(INPUTDIR) -o $$(OUTPUTDIR) -s $$(CONFFILE) $$(PELICANOPTS) + $(PELICAN) $(INPUTDIR) -o $(OUTPUTDIR) -s $(CONFFILE) $(PELICANOPTS) clean: - [ ! -d $$(OUTPUTDIR) ] || rm -rf $$(OUTPUTDIR) + [ ! -d $(OUTPUTDIR) ] || rm -rf $(OUTPUTDIR) regenerate: - $$(PELICAN) -r $$(INPUTDIR) -o $$(OUTPUTDIR) -s $$(CONFFILE) $$(PELICANOPTS) + $(PELICAN) -r $(INPUTDIR) -o $(OUTPUTDIR) -s $(CONFFILE) $(PELICANOPTS) serve: ifdef PORT - cd $$(OUTPUTDIR) && $(PY) -m pelican.server $$(PORT) + cd $(OUTPUTDIR) && $(PY) -m pelican.server $(PORT) else - cd $$(OUTPUTDIR) && $(PY) -m pelican.server + cd $(OUTPUTDIR) && $(PY) -m pelican.server endif serve-global: ifdef SERVER - cd $$(OUTPUTDIR) && $(PY) -m pelican.server 80 $$(SERVER) + cd $(OUTPUTDIR) && $(PY) -m pelican.server 80 $(SERVER) else - cd $$(OUTPUTDIR) && $(PY) -m pelican.server 80 0.0.0.0 + cd $(OUTPUTDIR) && $(PY) -m pelican.server 80 0.0.0.0 endif devserver: ifdef PORT - $$(BASEDIR)/develop_server.sh restart $$(PORT) + $(BASEDIR)/develop_server.sh restart $(PORT) else - $$(BASEDIR)/develop_server.sh restart + $(BASEDIR)/develop_server.sh restart endif stopserver: @@ -96,28 +122,49 @@ stopserver: @echo 'Stopped Pelican and SimpleHTTPServer processes running in background.' publish: - $$(PELICAN) $$(INPUTDIR) -o $$(OUTPUTDIR) -s $$(PUBLISHCONF) $$(PELICANOPTS) + $(PELICAN) $(INPUTDIR) -o $(OUTPUTDIR) -s $(PUBLISHCONF) $(PELICANOPTS) +{% set upload = [] %} +{% if ssh %} +{% set upload = upload + ["ssh_upload"] %} ssh_upload: publish - scp -P $$(SSH_PORT) -r $$(OUTPUTDIR)/* $$(SSH_USER)@$$(SSH_HOST):$$(SSH_TARGET_DIR) + scp -P $(SSH_PORT) -r $(OUTPUTDIR)/* $(SSH_USER)@$(SSH_HOST):$(SSH_TARGET_DIR) +{%- set upload = upload + ["rsync_upload"] -%} rsync_upload: publish rsync -e "ssh -p $(SSH_PORT)" -P -rvzc --cvs-exclude --delete $(OUTPUTDIR)/ $(SSH_USER)@$(SSH_HOST):$(SSH_TARGET_DIR) +{% endif %} +{% if dropbox %} +{% set upload = upload + ["dropbox_upload"] %} dropbox_upload: publish - cp -r $$(OUTPUTDIR)/* $$(DROPBOX_DIR) + cp -r $(OUTPUTDIR)/* $(DROPBOX_DIR) +{% endif %} +{% if ftp %} +{% set upload = upload + ["ftp_upload"] %} ftp_upload: publish - lftp ftp://$$(FTP_USER)@$$(FTP_HOST) -e "mirror -R $$(OUTPUTDIR) $$(FTP_TARGET_DIR) ; quit" + lftp ftp://$(FTP_USER)@$(FTP_HOST) -e "mirror -R $(OUTPUTDIR) $(FTP_TARGET_DIR) ; quit" +{% endif %} +{% if s3 %} +{% set upload = upload + ["s3_upload"] %} s3_upload: publish aws s3 sync $(OUTPUTDIR)/ s3://$(S3_BUCKET) --acl public-read --delete +{% endif %} +{% if cloudfiles %} +{% set upload = upload + ["cf_upload"] %} cf_upload: publish cd $(OUTPUTDIR) && swift -v -A https://auth.api.rackspacecloud.com/v1.0 -U $(CLOUDFILES_USERNAME) -K $(CLOUDFILES_API_KEY) upload -c $(CLOUDFILES_CONTAINER) . +{% endif %} +{% if github %} +{% set upload = upload + ["github"] %} github: publish - ghp-import -m "Generate Pelican site" -b $(GITHUB_PAGES_BRANCH) $$(OUTPUTDIR) + ghp-import -m "Generate Pelican site" -b $(GITHUB_PAGES_BRANCH) $(OUTPUTDIR) git push origin $(GITHUB_PAGES_BRANCH) -.PHONY: html help clean regenerate serve serve-global devserver stopserver publish ssh_upload rsync_upload dropbox_upload ftp_upload s3_upload cf_upload github +{% endif %} + +.PHONY: html help clean regenerate serve serve-global devserver stopserver publish {{ upload|join(" ") }} diff --git a/pelican/tools/templates/develop_server.sh.in b/pelican/tools/templates/develop_server.sh.jinja2 similarity index 51% rename from pelican/tools/templates/develop_server.sh.in rename to pelican/tools/templates/develop_server.sh.jinja2 index e345fefd..b8f6c029 100755 --- a/pelican/tools/templates/develop_server.sh.in +++ b/pelican/tools/templates/develop_server.sh.jinja2 @@ -2,23 +2,24 @@ ## # This section should match your Makefile ## -PELICAN=$${PELICAN:-$pelican} -PELICANOPTS=$pelicanopts +PY={{py_v}} +PELICAN=${PELICAN:-pelican} +PELICANOPTS={{pelicanopts}} -BASEDIR=$$(pwd) -INPUTDIR=$$BASEDIR/content -OUTPUTDIR=$$BASEDIR/output -CONFFILE=$$BASEDIR/pelicanconf.py +BASEDIR=$(pwd) +INPUTDIR=$BASEDIR/content +OUTPUTDIR=$BASEDIR/output +CONFFILE=$BASEDIR/pelicanconf.py ### # Don't change stuff below here unless you are sure ### -SRV_PID=$$BASEDIR/srv.pid -PELICAN_PID=$$BASEDIR/pelican.pid +SRV_PID=$BASEDIR/srv.pid +PELICAN_PID=$BASEDIR/pelican.pid function usage(){ - echo "usage: $$0 (stop) (start) (restart) [port]" + echo "usage: $0 (stop) (start) (restart) [port]" echo "This starts Pelican in debug and reload mode and then launches" echo "an HTTP server to help site development. It doesn't read" echo "your Pelican settings, so if you edit any paths in your Makefile" @@ -27,55 +28,55 @@ function usage(){ } function alive() { - kill -0 $$1 >/dev/null 2>&1 + kill -0 $1 >/dev/null 2>&1 } function shut_down(){ - PID=$$(cat $$SRV_PID) - if [[ $$? -eq 0 ]]; then + PID=$(cat $SRV_PID) + if [[ $? -eq 0 ]]; then if alive $PID; then echo "Stopping HTTP server" - kill $$PID + kill $PID else echo "Stale PID, deleting" fi - rm $$SRV_PID + rm $SRV_PID else echo "HTTP server PIDFile not found" fi - PID=$$(cat $$PELICAN_PID) - if [[ $$? -eq 0 ]]; then - if alive $$PID; then + PID=$(cat $PELICAN_PID) + if [[ $? -eq 0 ]]; then + if alive $PID; then echo "Killing Pelican" - kill $$PID + kill $PID else echo "Stale PID, deleting" fi - rm $$PELICAN_PID + rm $PELICAN_PID else echo "Pelican PIDFile not found" fi } function start_up(){ - local port=$$1 + local port=$1 echo "Starting up Pelican and HTTP server" shift - $$PELICAN --debug --autoreload -r $$INPUTDIR -o $$OUTPUTDIR -s $$CONFFILE $$PELICANOPTS & - pelican_pid=$$! - echo $$pelican_pid > $$PELICAN_PID - mkdir -p $$OUTPUTDIR && cd $$OUTPUTDIR - $PY -m pelican.server $$port & - srv_pid=$$! - echo $$srv_pid > $$SRV_PID - cd $$BASEDIR + $PELICAN --debug --autoreload -r $INPUTDIR -o $OUTPUTDIR -s $CONFFILE $PELICANOPTS & + pelican_pid=$! + echo $pelican_pid > $PELICAN_PID + mkdir -p $OUTPUTDIR && cd $OUTPUTDIR + $PY -m pelican.server $port & + srv_pid=$! + echo $srv_pid > $SRV_PID + cd $BASEDIR sleep 1 - if ! alive $$pelican_pid ; then + if ! alive $pelican_pid ; then echo "Pelican didn't start. Is the Pelican package installed?" return 1 - elif ! alive $$srv_pid ; then - echo "The HTTP server didn't start. Is there another service using port" $$port "?" + elif ! alive $srv_pid ; then + echo "The HTTP server didn't start. Is there another service using port" $port "?" return 1 fi echo 'Pelican and HTTP server processes now running in background.' @@ -84,17 +85,17 @@ function start_up(){ ### # MAIN ### -[[ ($$# -eq 0) || ($$# -gt 2) ]] && usage +[[ ($# -eq 0) || ($# -gt 2) ]] && usage port='' -[[ $$# -eq 2 ]] && port=$$2 +[[ $# -eq 2 ]] && port=$2 -if [[ $$1 == "stop" ]]; then +if [[ $1 == "stop" ]]; then shut_down -elif [[ $$1 == "restart" ]]; then +elif [[ $1 == "restart" ]]; then shut_down - start_up $$port -elif [[ $$1 == "start" ]]; then - if ! start_up $$port; then + start_up $port +elif [[ $1 == "start" ]]; then + if ! start_up $port; then shut_down fi else diff --git a/pelican/tools/templates/fabfile.py.in b/pelican/tools/templates/fabfile.py.jinja2 similarity index 83% rename from pelican/tools/templates/fabfile.py.in rename to pelican/tools/templates/fabfile.py.jinja2 index d3c50a83..eda60c42 100644 --- a/pelican/tools/templates/fabfile.py.in +++ b/pelican/tools/templates/fabfile.py.jinja2 @@ -14,17 +14,23 @@ from pelican.server import ComplexHTTPRequestHandler env.deploy_path = 'output' DEPLOY_PATH = env.deploy_path +{% if ssh %} # Remote server configuration -production = '$ssh_user@$ssh_host:$ssh_port' -dest_path = '$ssh_target_dir' +production = '{{ssh_user}}@{{ssh_host}}:{{ssh_port}}' +dest_path = '{{ssh_target_dir}}' +{% endif %} +{% if cloudfiles %} # Rackspace Cloud Files configuration settings -env.cloudfiles_username = '$cloudfiles_username' -env.cloudfiles_api_key = '$cloudfiles_api_key' -env.cloudfiles_container = '$cloudfiles_container' +env.cloudfiles_username = '{{cloudfiles_username}}' +env.cloudfiles_api_key = '{{cloudfiles_api_key}}' +env.cloudfiles_container = '{{cloudfiles_container}}' +{% endif %} +{% if github %} # Github Pages configuration -env.github_pages_branch = "$github_pages_branch" +env.github_pages_branch = '{{github_pages_branch}}' +{% endif %} # Port for `serve` PORT = 8000 @@ -68,6 +74,7 @@ def preview(): """Build production version of site""" local('pelican -s publishconf.py') +{% if cloudfiles %} def cf_upload(): """Publish to Rackspace Cloud Files""" rebuild() @@ -76,6 +83,7 @@ def cf_upload(): '-U {cloudfiles_username} ' '-K {cloudfiles_api_key} ' 'upload -c {cloudfiles_container} .'.format(**env)) +{% endif %} @hosts(production) def publish(): @@ -89,7 +97,9 @@ def publish(): extra_opts='-c', ) +{% if github %} def gh_pages(): """Publish to GitHub Pages""" rebuild() local("ghp-import -b {github_pages_branch} {deploy_path} -p".format(**env)) +{% endif %} diff --git a/pelican/tools/templates/pelicanconf.py.in b/pelican/tools/templates/pelicanconf.py.jinja2 similarity index 84% rename from pelican/tools/templates/pelicanconf.py.in rename to pelican/tools/templates/pelicanconf.py.jinja2 index 05d1a323..79f26a01 100644 --- a/pelican/tools/templates/pelicanconf.py.in +++ b/pelican/tools/templates/pelicanconf.py.jinja2 @@ -2,15 +2,15 @@ # -*- coding: utf-8 -*- # from __future__ import unicode_literals -AUTHOR = $author -SITENAME = $sitename +AUTHOR = {{author}} +SITENAME = {{sitename}} SITEURL = '' PATH = 'content' -TIMEZONE = $timezone +TIMEZONE = {{timezone}} -DEFAULT_LANG = $lang +DEFAULT_LANG = {{lang}} # Feed generation is usually not desired when developing FEED_ALL_ATOM = None @@ -29,7 +29,7 @@ LINKS = (('Pelican', 'http://getpelican.com/'), SOCIAL = (('You can add links in your config file', '#'), ('Another social link', '#'),) -DEFAULT_PAGINATION = $default_pagination +DEFAULT_PAGINATION = {{default_pagination}} # Uncomment following line if you want document-relative URLs when developing #RELATIVE_URLS = True diff --git a/pelican/tools/templates/publishconf.py.in b/pelican/tools/templates/publishconf.py.jinja2 similarity index 95% rename from pelican/tools/templates/publishconf.py.in rename to pelican/tools/templates/publishconf.py.jinja2 index 473490a9..4b9a7cba 100755 --- a/pelican/tools/templates/publishconf.py.in +++ b/pelican/tools/templates/publishconf.py.jinja2 @@ -11,7 +11,7 @@ sys.path.append(os.curdir) from pelicanconf import * # If your site is available via HTTPS, make sure SITEURL begins with https:// -SITEURL = '$siteurl' +SITEURL = '{{siteurl}}' RELATIVE_URLS = False FEED_ALL_ATOM = 'feeds/all.atom.xml'