Skip to content

Instantly share code, notes, and snippets.

@meyer
Last active August 8, 2016 02:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save meyer/4679035 to your computer and use it in GitHub Desktop.
Save meyer/4679035 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import mimetypes, sys
import datetime
from os import curdir, sep
from os.path import splitext
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
import codecs
try:
from jinja2 import Template, Environment, FileSystemLoader, nodes
from jinja2.ext import Extension
except ImportError:
print "Jinja template engine is not installed. Fix this with `pip install jinja2`"
exit(1)
DEBUG = True
TEMPLATE_DEBUG = True
jinja_env = Environment(extensions=[])
def do_indent_tabs(s, width=1, indentfirst=False, usetabs=False):
"""
Yoinked from Jinja2 source. thx babes.
"""
tab = u'\t'
if usetabs == False:
tab = ' '
indention = tab * width
rv = (u'\n' + indention).join(s.splitlines())
if indentfirst:
rv = indention + rv
return rv
jinja_globals = {}
jinja_env.loader = FileSystemLoader('.')
jinja_env.filters['indent'] = do_indent_tabs
server_port = 8080
# Could come in handy.
jinja_globals["current_year"] = datetime.datetime.now().year
jinja_globals["current_datestamp"] = datetime.datetime.now()
jinja_env.globals.update(jinja_globals)
class JinjaHandler(BaseHTTPRequestHandler):
def do_GET(self):
try:
path = self.path
if path.endswith('/'):
path += 'index.html'
path = _path = path.strip('/')
_path = list(path.rpartition('/')) # I LOVE YOU RPARTITION
save_as_file = False
if (_path[2].endswith('.html') or _path[2].endswith('.xml')) and not _path[2].startswith('_'):
_path[2] = '_' + _path[2]
save_as_file = True
_path = ''.join(_path)
# Open the _source file
source_file = codecs.open(curdir + sep + _path, "r")
self.send_response(200)
self.send_header('Content-type', mimetypes.guess_type(path)[0])
self.end_headers()
jinja_env.globals.update({"path":path})
if( save_as_file ):
template = jinja_env.from_string(source_file.read().decode('utf8')).render().encode('utf-8')
# Non-ASCII decoration. FIGHT ME.
# template += ("\n\n"
# "<!-- ┌──────────────────────────────────────────────────────┐ -->\n"
# "<!-- │ Rendered with serve.py on %s │ -->\n"
# "<!-- └──────────────────────────────────────────────────────┘ -->\n") % datetime.datetime.now()
self.wfile.write( template )
destination_file = open( curdir + sep + path, 'w' )
destination_file.write(template)
destination_file.close()
else:
self.wfile.write(source_file.read())
source_file.close()
return
except IOError, e:
import traceback, os.path
top = traceback.extract_stack()[-1]
self.wfile.write(
"<code>Error: %s<br>Details: %s</code>" %
(
type(e).__name__,
# os.path.basename(top[0]),
# str(top[1]),
e
)
)
return
# self.send_error(404,'File Not Found: %s' % self.path)
if __name__ == '__main__':
if (len(sys.argv) > 1):
try:
sys.argv[1] = int( sys.argv[1] )
server_port = sys.argv[1]
except:
print "Invalid port number:", sys.argv[1]
exit(1)
try:
httpd = HTTPServer(('',server_port), JinjaHandler)
print 'Server started on port %d, press Ctrl-C to stop' % server_port
httpd.serve_forever()
except KeyboardInterrupt:
print "\nShutting down..."
httpd.socket.close()
@agusmakmun
Copy link

agusmakmun commented Apr 22, 2016

Thanks so much for this tutorial 👍 , btw can you give me a simply how to add the context?
Example:

template = jinja_env.from_string(source_file.read().decode('utf8')).render().encode('utf-8')
self.wfile.write( template, {'awesome': 'This value of awesome'} ) #it will be an error because `template` is string, how to add it?

and then in the template:

{% if awesome %}
    {{ awesome }}
{% endif %}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment