# HG changeset patch # User cmlenz # Date 1149337918 0 # Node ID f8612f05af99048f5b978790150ada3bc628232f # Parent e86dcec16d5581ff4f50650a1d9ac5b9e1ab9f02 Added first stab of an implementation of the !TurboGears [http://www.turbogears.org/docs/plugins/template.html plugin API for template engines], and also a !TurboGears-based example using this plugin. Both written by Matt Good. diff --git a/examples/turbogears/README.txt b/examples/turbogears/README.txt new file mode 100644 --- /dev/null +++ b/examples/turbogears/README.txt @@ -0,0 +1,4 @@ +MarkupTest + +This is a TurboGears (http://www.turbogears.org) project. It can be +started by running the start-markuptest.py script. \ No newline at end of file diff --git a/examples/turbogears/dev.cfg b/examples/turbogears/dev.cfg new file mode 100644 --- /dev/null +++ b/examples/turbogears/dev.cfg @@ -0,0 +1,64 @@ +[global] +# This is where all of your settings go for your development environment +# Settings that are the same for both development and production +# (such as template engine, encodings, etc.) all go in +# markuptest/config/app.cfg + +# DATABASE + +# pick the form for your database +# sqlobject.dburi="postgres://username@hostname/databasename" +# sqlobject.dburi="mysql://username:password@hostname:port/databasename" +# sqlobject.dburi="sqlite:///file_name_and_path" + +# If you have sqlite, here's a simple default to get you started +# in development +sqlobject.dburi="sqlite://%(current_dir_uri)s/devdata.sqlite" + + +# if you are using a database or table type without transactions +# (MySQL default, for example), you should turn off transactions +# by prepending notrans_ on the uri +# sqlobject.dburi="notrans_mysql://username:password@hostname:port/databasename" + +# for Windows users, sqlite URIs look like: +# sqlobject.dburi="sqlite:///drive_letter:/path/to/file" + + +# SERVER + +# Some server parameters that you may want to tweak +# server.socket_port=8080 + +# Enable the debug output at the end on pages. +# log_debug_info_filter.on = False + +server.environment="development" +autoreload.package="markuptest" + +# Set to True if you'd like to abort execution if a controller gets an +# unexpected parameter. False by default +tg.strict_parameters = True + +# LOGGING +# Logging configuration generally follows the style of the standard +# Python logging module configuration. Note that when specifying +# log format messages, you need to use *() for formatting variables. +# Deployment independent log configuration is in markuptest/config/log.cfg +[logging] + +[[loggers]] +[[[markuptest]]] +level='DEBUG' +qualname='markuptest' +handlers=['debug_out'] + +[[[allinfo]]] +level='INFO' +handlers=['debug_out'] + +[[[access]]] +level='INFO' +qualname='turbogears.access' +handlers=['access_out'] +propagate=0 diff --git a/examples/turbogears/markuptest/__init__.py b/examples/turbogears/markuptest/__init__.py new file mode 100644 diff --git a/examples/turbogears/markuptest/config/__init__.py b/examples/turbogears/markuptest/config/__init__.py new file mode 100644 diff --git a/examples/turbogears/markuptest/config/app.cfg b/examples/turbogears/markuptest/config/app.cfg new file mode 100644 --- /dev/null +++ b/examples/turbogears/markuptest/config/app.cfg @@ -0,0 +1,44 @@ +[global] +# The settings in this file should not vary depending on the deployment +# environment. dev.cfg and prod.cfg are the locations for +# the different deployment settings. Settings in this file will +# be overridden by settings in those other files. + +# The commented out values below are the defaults + +# VIEW + +# which view (template engine) to use if one is not specified in the +# template name +# tg.defaultview = "kid" +tg.defaultview = "markup" +markup.search_path = ["%(current_dir_uri)s"] +markup.outputformat = "xml" + +# The following kid settings determine the settings used by the kid serializer. + +# One of (html|xml|json) +# kid.outputformat="html" + +# kid.encoding="utf-8" + +# The sitetemplate is used for overall styling of a site that +# includes multiple TurboGears applications +# tg.sitetemplate="" + +# Allow every exposed function to be called as json, +# tg.allow_json = False + +# Set to True if you'd like all of your pages to include MochiKit +# tg.mochikit_all = False + +# Set to True if the scheduler should be started +# tg.scheduler = False + +[/static] +static_filter.on = True +static_filter.dir = "%(top_level_dir)s/static" + +[/favicon.ico] +static_filter.on = True +static_filter.file = "%(top_level_dir)s/static/images/favicon.ico" diff --git a/examples/turbogears/markuptest/config/log.cfg b/examples/turbogears/markuptest/config/log.cfg new file mode 100644 --- /dev/null +++ b/examples/turbogears/markuptest/config/log.cfg @@ -0,0 +1,29 @@ +# LOGGING +# Logging is often deployment specific, but some handlers and +# formatters can be defined here. + +[logging] +[[formatters]] +[[[message_only]]] +format='*(message)s' + +[[[full_content]]] +format='*(asctime)s *(name)s *(levelname)s *(message)s' + +[[handlers]] +[[[debug_out]]] +class='StreamHandler' +level='DEBUG' +args='(sys.stdout,)' +formatter='full_content' + +[[[access_out]]] +class='StreamHandler' +level='INFO' +args='(sys.stdout,)' +formatter='message_only' + +[[[error_out]]] +class='StreamHandler' +level='ERROR' +args='(sys.stdout,)' diff --git a/examples/turbogears/markuptest/controllers.py b/examples/turbogears/markuptest/controllers.py new file mode 100644 --- /dev/null +++ b/examples/turbogears/markuptest/controllers.py @@ -0,0 +1,17 @@ +import logging + +import cherrypy + +import turbogears +from turbogears import controllers, expose, validate, redirect + +from markuptest import json + +log = logging.getLogger("markuptest.controllers") + +class Root(controllers.RootController): + @expose(template="markuptest.templates.welcome") + def index(self): + import time + log.debug("Happy TurboGears Controller Responding For Duty") + return dict(now=time.ctime()) diff --git a/examples/turbogears/markuptest/json.py b/examples/turbogears/markuptest/json.py new file mode 100644 --- /dev/null +++ b/examples/turbogears/markuptest/json.py @@ -0,0 +1,13 @@ +# This module provides helper functions for the JSON part of your +# view, if you are providing a JSON-based API for your app. + +# Here's what most rules would look like: +# @jsonify.when("isinstance(obj, YourClass)") +# def jsonify_yourclass(obj): +# return [obj.val1, obj.val2] +# +# The goal is to break your objects down into simple values: +# lists, dicts, numbers and strings + +from turbojson.jsonify import jsonify + diff --git a/examples/turbogears/markuptest/model.py b/examples/turbogears/markuptest/model.py new file mode 100644 --- /dev/null +++ b/examples/turbogears/markuptest/model.py @@ -0,0 +1,1 @@ + diff --git a/examples/turbogears/markuptest/release.py b/examples/turbogears/markuptest/release.py new file mode 100644 --- /dev/null +++ b/examples/turbogears/markuptest/release.py @@ -0,0 +1,13 @@ +# Release information about MarkupTest + +version = "1.0" + +# description = "Your plan to rule the world" +# author = "Your Name Here" +# email = "YourEmail@YourDomain" +# copyright = "Vintage 2006 - a good year indeed" + +# if it's open source, you might want to specify these +# url = "http://yourcool.site/" +# download_url = "http://yourcool.site/download" +# license = "MIT" diff --git a/examples/turbogears/markuptest/static/images/favicon.ico b/examples/turbogears/markuptest/static/images/favicon.ico new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..332557bc307647601389c14939be0671c62efcd7 GIT binary patch literal 1081 zc$@(_1jhSENk%w1VGsZi0Ow5rU0q$8Llvf`rg3p`iHV7;tE=$v@Z{v=e0+SkxVY1i zVbjyo_xJas3` z%*@QbzP_%muFlTRuXR$eu&|(@pvlR}#>U39w6vL-ncLgj_sv?eva+bCsJgnky}iAU zFbC)7=g`p5RFNg6++fty)Q5+M+-+j?^z?2p6YHcgZ*Feo?Dc7BY3=j=*}=5d*4FCk z>e$%WkZD%6mVNm6_)$?&^5)=2M@NQ3Cg0!R!<&WI$-#kvfuvL_*WKs;|Nrdl>}FEk`SkLhzMN`o zagv9Jfw4^C=I!{dq?(?k?eOvV@$SCE%$}mDz_6m>Xz`*|g{`&g*;^N}L z#?NMGZT|oN|Nj2#@%%wTLjL~$`T6<%{r&p;`}Xzq`~Cj#^77Hr)zs3`*VNL(wyegx zwdmZ{ok<+e(bVDL;o;)r_4W1k_V)Mo_07%AQ&Us!?(OO6>Few3%*VrGV`a+9-gXJ=SgSXx?J$iKM${{4J^g{GvV9UL4aBO}Yu&APj}r>CXM&&=!Z@#5p;>gwsi zzrDi2z?Pb!A^sIZa%Ew3Wn>_CX>@2HRA^-&M@dak04x9i000mG5C8xO{s5aaVb~md%O-2S^lHv64-i!($A}fp9Pe9y&;49CUHQ z;Fz%>4uYhycVZEqMJMv5!5PGul{9Hmczdy=sTptC(pZr~t0;$iDIKRaU;LNRWRnT0wg0}PMk>e#R#Md8k*YDvbIYV`E zcS*)_N8;Vt-{0T4i*l)rclP%7^78WR?CkR9;P$YDnnM-rm~X_Hf?6gCgI!D3*xIvn zQ{CO&=H}+Sp@`Jf)V8Uj(#^}_=IZF^=*z;rmu*C&dQ{-x;HiUM_4)eK$-?jO@apR7 z4`B0d{{=xteoB8;=Pe*n1FP(i(`00 zCd0L>(Y~|l?(u6oA$UtP`27CBuA8AxB)zPixrJ$+S~$(6kGzasu$G0tl6vUv@2XQK zfQ>0ljtdM-Vqm#KFMX+T796(dp~%*3;2vD+#Qelyox?%EiL-_V~t;T(y5=&(hTV{{OkB zo72X-v!k2Uw4&C#tI^Wbv{xzOdCvVzK(S3?e5yiz@JVdkvR$b{r=6)&)weN*q>+N;^X!7@z~DD_xk&9Kqikt z9OvrnwqG-EM=`>±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 + + + + + + + Login + + + + +
+

Login

+

$message

+
+ + + + + + + + + + + + +
+ + + +
+ + + +
+ +
+ + + + +
+
+ + diff --git a/examples/turbogears/markuptest/templates/master.html b/examples/turbogears/markuptest/templates/master.html new file mode 100644 --- /dev/null +++ b/examples/turbogears/markuptest/templates/master.html @@ -0,0 +1,40 @@ + + + + + + Your title goes here + ${select('*/*')} + + + + +
+ + Login + + + Welcome ${tg.identity.user.display_name}. + Logout + +
+ +
+ + ${select('*')} + +

TurboGears under the hood

+ + + diff --git a/examples/turbogears/markuptest/templates/welcome.html b/examples/turbogears/markuptest/templates/welcome.html new file mode 100644 --- /dev/null +++ b/examples/turbogears/markuptest/templates/welcome.html @@ -0,0 +1,35 @@ + + + + + + + Welcome to TurboGears + + + +

Congratulations, your TurboGears application is running as of now.

+ +

Are you ready to Gear Up?

+ +

Take the following steps to dive right in:

+ +
    +
  1. Edit your project's model.py to create SQLObjects representing the data you're working with
  2. +
  3. Edit your dev.cfg file to point to the database you'll be using
  4. +
  5. Run "tg-admin sql create" to create the tables in the database
  6. +
  7. Edit controllers.py to add the functionality to your webapp
  8. +
  9. Change the master.kid template to have the headers and footers for your application.
  10. +
  11. Change welcome.kid (this template) or create a new one to display your data
  12. +
  13. Repeat steps 4-6 until done.
  14. +
  15. Profit!
  16. +
+ +

If you haven't already, you might check out some of the documentation.

+ +

Thanks for using TurboGears! See you on the mailing list and the "turbogears" channel on irc.freenode.org!

+ + + diff --git a/examples/turbogears/markuptest/tests/__init__.py b/examples/turbogears/markuptest/tests/__init__.py new file mode 100644 diff --git a/examples/turbogears/markuptest/tests/test_controllers.py b/examples/turbogears/markuptest/tests/test_controllers.py new file mode 100644 --- /dev/null +++ b/examples/turbogears/markuptest/tests/test_controllers.py @@ -0,0 +1,16 @@ +from turbogears import testutil +from markuptest.controllers import Root +import cherrypy + +cherrypy.root = Root() + +def test_method(): + "the index method should return a string called now" + import types + result = testutil.call(cherrypy.root.index) + assert type(result["now"]) == types.StringType + +def test_indextitle(): + "The mainpage should have the right title" + testutil.createRequest("/") + assert "Welcome to TurboGears" in cherrypy.response.body[0] diff --git a/examples/turbogears/markuptest/tests/test_model.py b/examples/turbogears/markuptest/tests/test_model.py new file mode 100644 --- /dev/null +++ b/examples/turbogears/markuptest/tests/test_model.py @@ -0,0 +1,23 @@ +# If your project uses a database, you can set up database tests +# similar to what you see below. Be sure to set the db_uri to +# an appropriate uri for your testing database. sqlite is a good +# choice for testing, because you can use an in-memory database +# which is very fast. + +from turbogears import testutil +# from markuptest.model import YourDataClass, User + +# database.set_db_uri("sqlite:///:memory:") + +# class TestUser(testutil.DBTest): +# def get_model(self): +# return User +# +# def test_creation(self): +# "Object creation should set the name" +# obj = User(user_name = "creosote", +# email_address = "spam@python.not", +# display_name = "Mr Creosote", +# password = "Wafer-thin Mint") +# assert obj.display_name == "Mr Creosote" + diff --git a/examples/turbogears/sample-prod.cfg b/examples/turbogears/sample-prod.cfg new file mode 100644 --- /dev/null +++ b/examples/turbogears/sample-prod.cfg @@ -0,0 +1,66 @@ +[global] +# This is where all of your settings go for your production environment. +# You'll copy this file over to your production server and provide it +# as a command-line option to your start script. +# Settings that are the same for both development and production +# (such as template engine, encodings, etc.) all go in +# markuptest/config/app.cfg + +# DATABASE + +# pick the form for your database +# sqlobject.dburi="postgres://username@hostname/databasename" +# sqlobject.dburi="mysql://username:password@hostname:port/databasename" +# sqlobject.dburi="sqlite:///file_name_and_path" + +# if you are using a database or table type without transactions +# (MySQL default, for example), you should turn off transactions +# by prepending notrans_ on the uri +# sqlobject.dburi="notrans_mysql://username:password@hostname:port/databasename" + +# for Windows users, sqlite URIs look like: +# sqlobject.dburi="sqlite:///drive_letter|/path/to/file" + + +# SERVER + +server.environment="production" + +# Sets the number of threads the server uses +# server.thread_pool = 1 + +# if this is part of a larger site, you can set the path +# to the TurboGears instance here +# server.webpath="" + +# Set to True if you'd like to abort execution if a controller gets an +# unexpected parameter. False by default +# tg.strict_parameters = False + +# LOGGING +# Logging configuration generally follows the style of the standard +# Python logging module configuration. Note that when specifying +# log format messages, you need to use *() for formatting variables. +# Deployment independent log configuration is in markuptest/config/log.cfg +[logging] + +[[handlers]] + +[[[access_out]]] +# set the filename as the first argument below +args="('server.log',)" +class='FileHandler' +level='INFO' +formatter='message_only' + +[[loggers]] +[[[markuptest]]] +level='ERROR' +qualname='markuptest' +handlers=['error_out'] + +[[[access]]] +level='INFO' +qualname='turbogears.access' +handlers=['access_out'] +propagate=0 diff --git a/examples/turbogears/setup.py b/examples/turbogears/setup.py new file mode 100644 --- /dev/null +++ b/examples/turbogears/setup.py @@ -0,0 +1,62 @@ +from setuptools import setup, find_packages +from turbogears.finddata import find_package_data + +import os +execfile(os.path.join("markuptest", "release.py")) + +setup( + name="MarkupTest", + version=version, + + # uncomment the following lines if you fill them out in release.py + #description=description, + #author=author, + #author_email=email, + #url=url, + #download_url=download_url, + #license=license, + + install_requires = [ + "TurboGears >= 0.9a7dev-r1517", + ], + scripts = ["start-markuptest.py"], + zip_safe=False, + packages=find_packages(), + package_data = find_package_data(where='markuptest', + package='markuptest'), + keywords = [ + # Use keywords if you'll be adding your package to the + # Python Cheeseshop + + # if this has widgets, uncomment the next line + # 'turbogears.widgets', + + # if this has a tg-admin command, uncomment the next line + # 'turbogears.command', + + # if this has identity providers, uncomment the next line + # 'turbogears.identity.provider', + + # If this is a template plugin, uncomment the next line + # 'python.templating.engines', + + # If this is a full application, uncomment the next line + # 'turbogears.app', + ], + classifiers = [ + 'Development Status :: 3 - Alpha', + 'Operating System :: OS Independent', + 'Programming Language :: Python', + 'Topic :: Software Development :: Libraries :: Python Modules', + 'Framework :: TurboGears', + # if this is an application that you'll distribute through + # the Cheeseshop, uncomment the next line + # 'Framework :: TurboGears :: Applications', + + # if this is a package that includes widgets that you'll distribute + # through the Cheeseshop, uncomment the next line + # 'Framework :: TurboGears :: Widgets', + ], + test_suite = 'nose.collector', + ) + diff --git a/examples/turbogears/start-markuptest.py b/examples/turbogears/start-markuptest.py new file mode 100755 --- /dev/null +++ b/examples/turbogears/start-markuptest.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python +import pkg_resources +pkg_resources.require("TurboGears") + +import turbogears +import cherrypy +cherrypy.lowercase_api = True + +from os.path import * +import sys + +# first look on the command line for a desired config file, +# if it's not on the command line, then +# look for setup.py in this directory. If it's not there, this script is +# probably installed +if len(sys.argv) > 1: + turbogears.update_config(configfile=sys.argv[1], + modulename="markuptest.config") +elif exists(join(dirname(__file__), "setup.py")): + turbogears.update_config(configfile="dev.cfg", + modulename="markuptest.config") +else: + turbogears.update_config(configfile="prod.cfg", + modulename="markuptest.config") + +from markuptest.controllers import Root + +turbogears.start_server(Root()) diff --git a/markup/plugin.py b/markup/plugin.py new file mode 100644 --- /dev/null +++ b/markup/plugin.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2006 Mattew Good +# All rights reserved. +# +# This software is licensed as described in the file COPYING, which +# you should have received as part of this distribution. The terms +# are also available at http://trac.edgewall.com/license.html. +# +# This software consists of voluntary contributions made by many +# individuals. For the exact contribution history, see the revision +# history and logs, available at http://projects.edgewall.com/trac/. + +import os +from pkg_resources import resource_filename + +from markup.template import Context, Template, TemplateLoader + + +class TemplateEnginePlugin(object): + + def __init__(self, extra_vars_func=None, options=None): + if options is None: + options = {} + # TODO get loader_args from the options dict + + self.loader = TemplateLoader(auto_reload=True) + self.options = options + self.get_extra_vars = extra_vars_func + + def load_template(self, templatename): + """Find a template specified in python 'dot' notation.""" + divider = templatename.rfind('.') + if divider >= 0: + package = templatename[:divider] + basename = templatename[divider + 1:] + '.html' + fullpath = resource_filename(package, basename) + dirname, templatename = os.path.split(fullpath) + self.loader.search_path.append(dirname) # Kludge + + return self.loader.load(templatename) + + def render(self, info, format='html', fragment=False, template=None): + """Renders the template to a string using the provided info.""" + return self.transform(info, template).render(method=format) + + def transform(self, info, template): + "Render the output to Elements" + if not isinstance(template, Template): + template = self.load_template(template) + + data = {} + if self.get_extra_vars: + data.update(self.get_extra_vars()) + data.update(info) + + ctxt = Context(**data) + return template.generate(ctxt) diff --git a/setup.py b/setup.py --- a/setup.py +++ b/setup.py @@ -21,5 +21,9 @@ license='BSD', url='http://markup.cmlenz.net/', packages=find_packages(exclude=['*.tests*']), test_suite = 'markup.tests.suite', - zip_safe = True + zip_safe = True, + entry_points = """ + [python.templating.engines] + markup = markup.plugin:TemplateEnginePlugin + """, )