d3fd3c7a79c0 — Oben Sonne 11 months ago
merge py3 into default (Poolo is now P3 only)
M .travis.yml +3 -1
@@ 1,6 1,8 @@ 
 language: python
 python:
-  - "2.7"
+  - "3.2"
+  - "3.3"
+  - "3.6"
 install:
   - "pip install markdown"
 script:

          
M README.md +6 -6
@@ 32,7 32,7 @@ yours).
 **You** should know Markdown and optionally Python if you want to use Poole's
 dirty content generation capability.
 
-**Your system** should have installed Python ≥ 2.7 and [python-markdown][pymd].
+**Your system** should have installed Python ≥ 3.2 and [python-markdown][pymd].
 Poole has been tested on Linux but should also work on other Unix systems and
 Windows (in theory, [report an issue][issues] if it fails).
 

          
@@ 109,16 109,16 @@ Every Poole page is based on the skeleto
 site layout means adjusting `page.html` and extending or replacing its CSS file
 `input/poole.css`.
 
-The only thing you should keep in `page.html` are the embedded
-{{\_\_content\_\_}} and {{\_\_encoding\_\_}} expressions.  Below is an almost
-minimal `page.html` file. It does not look nice but it's a clean starting point
-to build your own layout from scratch.
+The only thing you should keep in `page.html` is the embedded
+{{\_\_content\_\_}} expression.  Below is an almost minimal `page.html` file.
+It does not look nice but it's a clean starting point to build your own layout
+from scratch.
 
 Minimal `page.html`:
 
     <html>
       <head>
-        <meta http-equiv="Content-Type" content="text/html; charset={{ __encoding__ }}" />
+        <meta http-equiv="Content-Type" content="text/html; charset=utf8" />
       </head>
       <body>
         {{ __content__ }}

          
M poole.py +20 -32
@@ 23,7 23,6 @@ 
 #
 # =============================================================================
 
-import codecs
 import glob
 import imp
 import optparse

          
@@ 32,16 31,18 @@ from os.path import join as opj
 from os.path import exists as opx
 import re
 import shutil
-import StringIO
+import io
 import sys
 import traceback
-import urlparse
+import urllib.parse
 
-from SimpleHTTPServer import SimpleHTTPRequestHandler
-from BaseHTTPServer import HTTPServer
+from http.server import SimpleHTTPRequestHandler
+from http.server import HTTPServer
 
 import markdown
 
+UTF8 = 'UTF8'
+
 HERE = os.path.dirname(os.path.realpath(__file__))
 
 THEME_DIR = opj(HERE, 'themes')

          
@@ 61,7 62,7 @@ EXAMPLE_FILES =  {
 "page.html": """<!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" lang="en" xml:lang="en">
 <head>
-    <meta http-equiv="Content-Type" content="text/html; charset={{ __encoding__ }}" />
+    <meta http-equiv="Content-Type" content="text/html; charset=utf8" />
     <title>poole - {{ hx(page["title"]) }}</title>
     <meta name="description" content="{{ hx(page.get("description", "a poole site")) }}" />
     <meta name="keywords" content="{{ hx(page.get("keywords", "poole")) }}" />

          
@@ 204,7 205,7 @@ posts = [p for p in pages if "post" in p
 posts.sort(key=lambda p: p.get("date"), reverse=True) # sort post pages by date
 for p in posts:
     date = datetime.strptime(p.date, "%Y-%m-%d").strftime("%B %d, %Y")
-    print "  * **[%s](%s)** - %s" % (p.post, p.url, date) # markdown list item
+    print("  * **[%s](%s)** - %s" % (p.post, p.url, date)) # markdown list item
 %-->
 
 Have a look into `input/blog.md` to see how it works. Feel free to adjust it

          
@@ 221,7 222,7 @@ opj("input", "blog.2013-04-08.Lorem_Ipsu
 *Posted at
 <!--%
 from datetime import datetime
-print datetime.strptime(page["date"], "%Y-%m-%d").strftime("%B %d, %Y")
+print(datetime.strptime(page["date"], "%Y-%m-%d").strftime("%B %d, %Y"))
 %-->*
 
 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed sed pretium arcu.

          
@@ 276,7 277,7 @@ She looks like one. Why do you think tha
 her forward!
 
 [Ni!](http://chrisvalleskey.com/fillerama/)
-""",
+"""
 }
 
 def init(project, theme):

          
@@ 297,7 298,7 @@ def init(project, theme):
 
     for fname, content in EXAMPLE_FILES.items():
         print('info: create example %r' % fname)
-        with open(opj(project, fname), 'w') as fp:
+        with open(opj(project, fname), 'w', encoding=UTF8) as fp:
             fp.write(content)
 
     if theme != 'minimal':

          
@@ 385,7 386,7 @@ class Page(dict):
         if virtual:
             self.raw = virtual
         else:
-            with codecs.open(fname, 'r', self._opts.input_enc) as fp:
+            with open(fname, 'r', encoding=UTF8) as fp:
                 self.raw = fp.readlines()
 
         # split raw content into macro definitions and real content

          
@@ 452,7 453,7 @@ def build(project, opts):
     regx_escp = re.compile(r'\\((?:(?:&lt;|<)!--|{)(?:{|%))') # escaped code
     repl_escp = r'\1'
     regx_rurl = re.compile(r'(?<=(?:(?:\n| )src|href)=")([^#/&%].*?)(?=")')
-    repl_rurl = lambda m: urlparse.urljoin(opts.base_url, m.group(1))
+    repl_rurl = lambda m: urllib.parse.urljoin(opts.base_url, m.group(1))
 
     regx_eval = re.compile(r'(?<!\\)(?:(?:<!--|{){)(.*?)(?:}(?:-->|}))', re.S)
 

          
@@ 465,11 466,7 @@ def build(project, opts):
         except:
             abort_iex(page, "expression", expr, traceback.format_exc())
         else:
-            if not isinstance(repl, basestring): # e.g. numbers
-                repl = unicode(repl)
-            elif not isinstance(repl, unicode):
-                repl = repl.decode("utf-8")
-            return repl
+            return str(repl)
 
     regx_exec = re.compile(r'(?<!\\)(?:(?:<!--|{)%)(.*?)(?:%(?:-->|}))', re.S)
 

          
@@ 484,17 481,15 @@ def build(project, opts):
         stmt = ind_rex.sub('', stmt)
 
         # execute
-        sys.stdout = StringIO.StringIO()
+        sys.stdout = io.StringIO()
         try:
-            exec stmt in macros.copy()
+            exec(stmt, macros.copy())
         except:
             sys.stdout = sys.__stdout__
             abort_iex(page, "statements", stmt, traceback.format_exc())
         else:
             repl = sys.stdout.getvalue()[:-1] # remove last line break
             sys.stdout = sys.__stdout__
-            if not isinstance(repl, unicode):
-                repl = repl.decode(opts.input_enc)
             return repl
 
     # -------------------------------------------------------------------------

          
@@ 526,7 521,6 @@ def build(project, opts):
     fname = opj(opts.project, "macros.py")
     macros = imp.load_source("macros", fname).__dict__ if opx(fname) else {}
 
-    macros["__encoding__"] = opts.output_enc
     macros["options"] = opts
     macros["project"] = project
     macros["input"] = dir_in

          
@@ 547,7 541,7 @@ def build(project, opts):
     pages = []
     custom_converter = macros.get('converter', {})
 
-    for cwd, dirs, files in os.walk(dir_in.decode(opts.filename_enc)):
+    for cwd, dirs, files in os.walk(dir_in):
         cwd_site = cwd[len(dir_in):].lstrip(os.path.sep)
         if not opts.dry_run:
             for sdir in dirs[:]:

          
@@ 622,14 616,14 @@ def build(project, opts):
     # render complete HTML pages
     # -------------------------------------------------------------------------
 
-    with codecs.open(opj(project, "page.html"), 'r', opts.input_enc) as fp:
+    with open(opj(project, "page.html"), 'r', encoding=UTF8) as fp:
         default_template = fp.read()
 
     for page in pages:
 
         if 'template' in page:
             fname = opj(project, page['template'])
-            with codecs.open(fname, 'r', opts.input_enc) as fp:
+            with open(fname, 'r', opts.input_enc) as fp:
                 template = fp.read()
         else:
             template = default_template

          
@@ 652,7 646,7 @@ def build(project, opts):
         fname = page.fname.replace(dir_in, dir_out)
         fname = re.sub(MKD_PATT, ".html", fname)
         if not opts.dry_run:
-            with codecs.open(fname, 'w', opts.output_enc) as fp:
+            with open(fname, 'w', encoding=UTF8) as fp:
                 fp.write(out)
 
     if opts.dry_run:

          
@@ 712,12 706,6 @@ def options():
                   help="input files to ignore (default: '^\.|~$')")
     og.add_option("" , "--md-ext", default=[], metavar="EXT",
                   action="append", help="enable a markdown extension")
-    og.add_option("", "--input-enc", default="utf-8", metavar="ENC",
-                  help="encoding of input pages (default: utf-8)")
-    og.add_option("", "--output-enc", default="utf-8", metavar="ENC",
-                  help="encoding of output pages (default: utf-8)")
-    og.add_option("", "--filename-enc", default="utf-8", metavar="ENC",
-                  help="encoding of file names (default: utf-8)")
     og.add_option("" , "--dry-run", action="store_true", default=False,
                   help="go through the rendering process without actually "
                     "outputting/deleting any files")

          
M tests/expected/input/blog.2013-04-08.Lorem_Ipsum.md +1 -1
@@ 6,7 6,7 @@ 
 *Posted at
 <!--%
 from datetime import datetime
-print datetime.strptime(page["date"], "%Y-%m-%d").strftime("%B %d, %Y")
+print(datetime.strptime(page["date"], "%Y-%m-%d").strftime("%B %d, %Y"))
 %-->*
 
 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed sed pretium arcu.

          
M tests/expected/input/blog.md +1 -1
@@ 12,7 12,7 @@ posts = [p for p in pages if "post" in p
 posts.sort(key=lambda p: p.get("date"), reverse=True) # sort post pages by date
 for p in posts:
     date = datetime.strptime(p.date, "%Y-%m-%d").strftime("%B %d, %Y")
-    print "  * **[%s](%s)** - %s" % (p.post, p.url, date) # markdown list item
+    print("  * **[%s](%s)** - %s" % (p.post, p.url, date)) # markdown list item
 %-->
 
 Have a look into `input/blog.md` to see how it works. Feel free to adjust it

          
M tests/expected/output/blog.2013-04-01.Holy_Grail.html +1 -1
@@ 1,7 1,7 @@ 
 <!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" lang="en" xml:lang="en">
 <head>
-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    <meta http-equiv="Content-Type" content="text/html; charset=utf8" />
     <title>poole - blog</title>
     <meta name="description" content="a poole site" />
     <meta name="keywords" content="poole" />

          
M tests/expected/output/blog.2013-04-08.Lorem_Ipsum.html +1 -1
@@ 1,7 1,7 @@ 
 <!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" lang="en" xml:lang="en">
 <head>
-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    <meta http-equiv="Content-Type" content="text/html; charset=utf8" />
     <title>poole - blog</title>
     <meta name="description" content="a poole site" />
     <meta name="keywords" content="poole" />

          
M tests/expected/output/blog.html +1 -1
@@ 1,7 1,7 @@ 
 <!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" lang="en" xml:lang="en">
 <head>
-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    <meta http-equiv="Content-Type" content="text/html; charset=utf8" />
     <title>poole - blog</title>
     <meta name="description" content="a poole site" />
     <meta name="keywords" content="poole" />

          
M tests/expected/output/index.html +1 -1
@@ 1,7 1,7 @@ 
 <!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" lang="en" xml:lang="en">
 <head>
-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    <meta http-equiv="Content-Type" content="text/html; charset=utf8" />
     <title>poole - home</title>
     <meta name="description" content="a poole site" />
     <meta name="keywords" content="poole" />

          
M tests/expected/output/layout.html +1 -1
@@ 1,7 1,7 @@ 
 <!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" lang="en" xml:lang="en">
 <head>
-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    <meta http-equiv="Content-Type" content="text/html; charset=utf8" />
     <title>poole - layout</title>
     <meta name="description" content="a poole site" />
     <meta name="keywords" content="poole" />

          
M tests/expected/output/logic.html +1 -1
@@ 1,7 1,7 @@ 
 <!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" lang="en" xml:lang="en">
 <head>
-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    <meta http-equiv="Content-Type" content="text/html; charset=utf8" />
     <title>poole - logic</title>
     <meta name="description" content="a poole site" />
     <meta name="keywords" content="poole" />

          
M tests/expected/page.html +1 -1
@@ 1,7 1,7 @@ 
 <!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" lang="en" xml:lang="en">
 <head>
-    <meta http-equiv="Content-Type" content="text/html; charset={{ __encoding__ }}" />
+    <meta http-equiv="Content-Type" content="text/html; charset=utf8" />
     <title>poole - {{ hx(page["title"]) }}</title>
     <meta name="description" content="{{ hx(page.get("description", "a poole site")) }}" />
     <meta name="keywords" content="{{ hx(page.get("keywords", "poole")) }}" />

          
M tests/run.py +2 -3
@@ 1,6 1,5 @@ 
 #!/usr/bin/env python
 
-import codecs
 import os
 import shutil
 import subprocess

          
@@ 49,8 48,8 @@ if generated == []:
 p = subprocess.Popen(cmd_diff, stdout=subprocess.PIPE)
 diff = p.communicate()[0]
 if diff:
-    with codecs.open(ERRORS, 'w', 'UTF8') as fp:
-        fp.write(diff.decode('UTF8'))
+    with open(ERRORS, 'wb') as fp:
+        fp.write(diff)
     print("failed - see %s for details" % ERRORS)
     sys.exit(1)