Dirty: Python 3.0으로 작성된 HTML/XML 템플릿 엔진 모듈
전에 소개한 적 있던 웹 프레임워크 프로젝트인 Vlastic의 튜토리얼 문서를 쓰기로 했다. 그런데 사실 Vlastic 프레임워크는 웹 애플리케이션을 RESTful하게 작성하는 부분까지만 제공할 뿐, ORM 따위의 퍼시스트 객체 프레임워크라던가, HTML 템플릿 엔진 따위는 포함하지 않기로 결정한 상태라—사람마다 취향이 다르기 때문에, 각자 편한 것을 사용할 수 있도록—튜토리얼에서 HTML 마크업을 일일히 문자열로 쓰게 생겼다. 물론 Python 3.0에서 추가된 새로운 문자열 서식자가 꽤나 강력하긴 하지만 분기 처리나 루프 따위를 지원하는 것은 아니라서 웹 애플리케이션 작성하는 용도로 쓰기는 힘들다.
그래서 간단하게 Python 3.0으로 HTML/XML 템플릿 엔진을 작성하기로 했다. 사실 2to3.py로 Jinja2라거나 Kid 같은 템플릿 엔진을 옮겨도 되지만, 두 가지 이유 때문에 그렇게 하지 않았다.
- 튜토리얼 안에 2to3.py를 이용해 템플릿 엔진을 Python 3.0 코드로 변환하는 작업을 넣긴 애매했다. 튜토리얼이잖아.
- Vlastic은 응답 문자열을 모두 버퍼링하는 방식을 벗어나는 것이 중요한 기능 중 하나인데, 템플릿 엔진이 버퍼링을 해서 문자열을 통째로 줘버리면 의미가 없기 때문이다. 내가 알기로, 기존에 Python으로 작성된 템플릿 엔진 가운데 전체 문자열을 다 버퍼링하지 않는 구현이 없다.
그러니까 요구사항을 추출하기는 쉽다.
- Python 3.0으로 작성해야 한다.
- 전체 출력 문자열을 버퍼링하지 않아야 한다. 즉, 출력을 반복자(iterator)나 유사 파일 객체(file-like object)로 반환해야 한다.
요구사항에 문법의 깔끔함 따위는 들어있지 않다. 그래서, 파서 작성하기도 귀찮은데 잘됐다 하고 Markaby 비슷하게 EDSL(DSEL)로 가기로 했다. 그래서 나온 문법이 이렇다.
>>> from dirty.html import *
>>> page = xhtml(
... head(
... title("Dirty"),
... meta(name="Author", content="Hong, MinHee <minhee@dahlia.kr>")
... ),
... body(
... h1("Dirty"),
... p("Dirty is a simple DSEL template library that...")
... )
... )
>>> print(page)
<!DOCTYPE html PUBLIC
"-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" /><head><title>Dirty</title><meta content="Hong, MinHee <minhee@dahlia.kr>" name="Author" /></head><body><h1>Dirty</h1><p>Dirty is a simple DSEL template library that...</p></body></html>
보다시피 애초에 문법 자체가 Python 함수 호출 형식일 뿐이고, 출력 결과는 공백 문자 제어가 전혀 되지 않고 있어서 지저분하기 그지없다. 그래서 이름도 Dirty라고 지었다. 아 드러.
모듈은 구글 프로젝트 호스팅으로 공개했다. 라이센스는 LGPL이다. 아래 사이트에서 소스 패키지를 받거나 Subversion으로 체크아웃할 수 있다.
