All pastes #633962 Raw Edit

Stuff

public python v1 · immutable
#633962 ·published 2007-07-26 01:51 UTC
rendered paste body
##            DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE#                    Version 2, December 2004## Copyright (C) 2004 Sam Hocevar#  14 rue de Plaisance, 75014 Paris, France# Everyone is permitted to copy and distribute verbatim or modified# copies of this license document, and changing it is allowed as long# as the name is changed.##            DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE#   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION##  0. You just DO WHAT THE FUCK YOU WANT TO.### This is a template language.# It's a bit different from the others you may encounter, however, in that you have to parse your template manually.# This is a bit of an odd concept for some used to working with more complex template systems at first, but let me explain.## The current syntax is {[block_open]} {{variable}} {[/block_close]}.# Let's say we have a file called foo.plnr that looks like so:##     {[block]}#         {{variable}}#     {[/block]}#     {{variable}}## In the code, we'd process this with the following:##     from planar import *#     tpl = Template('foo.plnr')##     for i in range(0, 10):#         tpl.block.assign('variable', i)#         tpl.block.parse()##     tpl.assign('variable', 'outside of the block scope')#     tpl.parse()##     print tpl## Essentially, you're responsible for parsing it all yourself.  There's no logic in the template at all.# Planar is designed to be used as a very thin layer on top of your application.#__all__ = ['Template']MODE_VAR            = -1MODE_BLOCK_CONTENTS = -2MODE_BLOCK_OPEN     = -3MODE_BLOCK_CLOSE    = -4legal = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-'class WhatTheShitAreYouDoingException(Exception):	passclass MalformedTemplateException(WhatTheShitAreYouDoingException):	passclass Block:	"""This is the basic class for handling blocks.  It provides the following functions:	from_string(content)     - Creates a block out of an already-processed string.  You should not use this.	assign(var[, value])     - Assigns a value to a variable.  var can be a dictionary of var: value pairs.	parse([flush_children])  - Parse the block one time.  If flush_children is true, the children will not be flushed (this is typically an undesirable action).	flush()                  - Clear the internal buffer of parsed outputs.	render()                 - Return a string representation of the block."""		flush_children = ''	def __str__(self):		return self.render()	def __init__(self, block_id, content = False):		self.block_id = block_id		self.content  = ''		self.compiled = None		self.fcmd     = None		self.output   = []		self.vars     = {}		if content:			self.from_string(content)	def from_string(self, content):		self.content = content				self.compiled = compile("'''" + content + "'''", '<string>', 'eval')		self.fcmd     = compile(self.flush_children, '<string>', 'exec')	def assign(self, var, val = False):		if type(var) == dict:			for k in var:				self.vars[k] = str(var[k])		elif val or (type(val) != bool and not val):			self.vars[str(var)] = str(val)		else:			return False		def parse(self, flush_children = True):		try:			self.output.append(eval(self.compiled))		except KeyError:			raise WhatTheShitAreYouDoingException, "You're missing a variable when you try to parse block '%s'" % self.block_id		if flush_children:			eval(self.fcmd)	def flush(self):		self.output = []			def render(self):		return "".join(self.output)## somebody is going to have my head for this#def Template(tplfile):	"""This function parses a file for blocks and variables.  This is probably all that you'll want to use here."""		b_id   = []	b_cont = []	id     = ''	mode   = False	offset = 0		c = p = False	o = ''	f = open(tplfile)		root = Block('root')		while c != '':		p = c		c = f.read(1)		if not mode:			if c == '{':				mode = True				id = ''			else:				o += c		else:			if mode <= MODE_BLOCK_OPEN:				if not c in legal + '/]':					o += '{'										if mode == MODE_VAR:						o += '{'					elif mode == MODE_BLOCK_OPEN:						o += '['					elif mode == MODE_BLOCK_CLOSE:						o += '[/'											o += id + c					mode = False					continue				elif c == ']':					if mode == MODE_BLOCK_CLOSE:						if b_id[len(b_id)-1] == id:							# block close														exec('root.' + '.'.join(b_id) + ".from_string('''" + o.replace("'", "\\'") + "''')")														s = b_id.pop()							o = b_cont.pop()														o += "''' + self." + id + ".render() + '''"							if len(b_id) > 0:								exec('root.' + '.'.join(b_id) + '.flush_children += "self.' + s + '.flush(); "')							elif len(b_id) == 0:								exec('root.flush_children += "self.' + s + '.flush(); "')						else:							raise MalformedTemplateException, "Blocks '%s' and '%s' are interleaved." % (b_id[len(b_id)-1], id)					else:						# block open												b_id.append(id)						try:							eval('root.' + '.'.join(b_id))														raise MalformedTemplateException, "Block %s was previously defined in context %s." % (id, '.'.join(b_id[:len(b_id)-1]))						except SyntaxError:							raise MalformedTemplateException, "Malformed token '%s'" % id						except AttributeError:							exec('root.' + '.'.join(b_id) + '= Block("' + '.'.join(b_id) + '")')						b_cont.append(o)						o = ''					id = ''					mode = True				elif c == '/':					if id != '':						raise MalformedTemplateException, "Malformed token '%s'" % id					else:						mode = MODE_BLOCK_CLOSE				else:					id += c			elif mode == MODE_VAR:				if not c in legal + '}':					raise MalformedTemplateException, "Unclosed or malformed token '%s'" % id				elif c == '}':					o += "''' + self.vars['" + id + "'] + '''"										id = ''					mode = True				else:					id += c			elif c == '{':				mode = MODE_VAR			elif c == '[':				mode = MODE_BLOCK_OPEN			else:				if c == '}':					if id != '':						raise MalformedTemplateException, "Unclosed token '%s'" % id				if p == '{':					o += p + c					mode = False									if mode == MODE_BLOCK_OPEN:					mode = MODE_BLOCK_CONTENTS				else:					mode = False		root.from_string(o)		return root