Skip to content

Commit ab9e902

Browse files
committed
Merge pull request #10 from rczajka/develop
Py3-compatible get_version in setup.py.
2 parents 271d93f + 4bb7c65 commit ab9e902

8 files changed

Lines changed: 184 additions & 77 deletions

File tree

setup.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@
1717
def get_version():
1818
basedir = os.path.dirname(__file__)
1919
with open(os.path.join(basedir, 'textile/version.py')) as f:
20-
VERSION = None
21-
exec(f.read())
22-
return VERSION
20+
variables = {}
21+
exec(f.read(), variables)
22+
return variables.get('VERSION')
2323
raise RuntimeError('No version info found.')
2424

2525
setup(

textile/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from __future__ import unicode_literals
2+
13
from .core import textile, textile_restricted, Textile
24
from .version import VERSION
35

textile/core.py

Lines changed: 59 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#!/usr/bin/env python
22
# -*- coding: utf-8 -*-
3+
from __future__ import unicode_literals
34

45
__copyright__ = """
56
Copyright (c) 2009, Jason Samsa, http://jsamsa.com/
@@ -75,7 +76,7 @@ class Textile(object):
7576

7677
pnct_re_s = r'[-!"#$%&()*+,/:;<=>?@\'\[\\\]\.^_`{|}~]'
7778
urlchar_re_s = r'[\w"$\-_.+!*\'(),";\/?:@=&%#{}|\\^~\[\]`]'
78-
syms_re_s = u'¤§µ¶†‡•∗∴◊♠♣♥♦'
79+
syms_re_s = '¤§µ¶†‡•∗∴◊♠♣♥♦'
7980

8081
restricted_url_schemes = ('http', 'https', 'ftp', 'mailto')
8182
unrestricted_url_schemes = restricted_url_schemes + ('file', 'tel',
@@ -181,9 +182,9 @@ def __init__(self, restricted=False, lite=False, noimage=False,
181182
# plus/minus
182183
re.compile(r'[([]\+\/-[])]', re.I | re.U),
183184
# 3+ uppercase acronym
184-
regex.compile(u'\\b([\\p{Lu}][\\p{Lu}0-9]{2,})\\b(?:[(]([^)]*)[)])'),
185+
regex.compile(r'\b([\p{Lu}][\p{Lu}0-9]{2,})\b(?:[(]([^)]*)[)])'),
185186
# 3+ uppercase
186-
regex.compile(u"""(?:(?<=^)|(?<=\\s)|(?<=[>\\(;-]))([\\p{Lu}]{3,})(\\w*)(?=\\s|%s|$)(?=[^">]*?(<|$))""" %
187+
regex.compile(r"""(?:(?<=^)|(?<=\s)|(?<=[>\(;-]))([\p{Lu}]{3,})(\w*)(?=\s|%s|$)(?=[^">]*?(<|$))""" %
187188
self.pnct_re_s),
188189
]
189190

@@ -235,7 +236,7 @@ def __init__(self, restricted=False, lite=False, noimage=False,
235236
def parse(self, text, rel=None, head_offset=0, sanitize=False):
236237
"""
237238
>>> import textile
238-
>>> textile.textile('some textile')
239+
>>> Py3 << textile.textile('some textile')
239240
'\\t<p>some textile</p>'
240241
"""
241242
self.notes = OrderedDict()
@@ -275,48 +276,48 @@ def pba(self, block_attributes, element=None):
275276
Parse block attributes.
276277
277278
>>> t = Textile()
278-
>>> t.pba(r'\3')
279+
>>> Py3 << t.pba(r'\3')
279280
''
280-
>>> t.pba(r'\\3', element='td')
281+
>>> Py3 << t.pba(r'\\3', element='td')
281282
' colspan="3"'
282-
>>> t.pba(r'/4', element='td')
283+
>>> Py3 << t.pba(r'/4', element='td')
283284
' rowspan="4"'
284-
>>> t.pba(r'\\3/4', element='td')
285+
>>> Py3 << t.pba(r'\\3/4', element='td')
285286
' colspan="3" rowspan="4"'
286287
287-
>>> t.pba('^', element='td')
288+
>>> Py3 << t.pba('^', element='td')
288289
' style="vertical-align:top;"'
289290
290-
>>> t.pba('{line-height:18px}')
291+
>>> Py3 << t.pba('{line-height:18px}')
291292
' style="line-height:18px;"'
292293
293-
>>> t.pba('(foo-bar)')
294+
>>> Py3 << t.pba('(foo-bar)')
294295
' class="foo-bar"'
295296
296-
>>> t.pba('(#myid)')
297+
>>> Py3 << t.pba('(#myid)')
297298
' id="myid"'
298299
299-
>>> t.pba('(foo-bar#myid)')
300+
>>> Py3 << t.pba('(foo-bar#myid)')
300301
' class="foo-bar" id="myid"'
301302
302-
>>> t.pba('((((')
303+
>>> Py3 << t.pba('((((')
303304
' style="padding-left:4em;"'
304305
305-
>>> t.pba(')))')
306+
>>> Py3 << t.pba(')))')
306307
' style="padding-right:3em;"'
307308
308-
>>> t.pba('[fr]')
309+
>>> Py3 << t.pba('[fr]')
309310
' lang="fr"'
310311
311-
>>> t.pba(r'\\5 80', 'col')
312+
>>> Py3 << t.pba(r'\\5 80', 'col')
312313
' span="5" width="80"'
313314
314315
>>> rt = Textile()
315316
>>> rt.restricted = True
316-
>>> rt.pba('[en]')
317+
>>> Py3 << rt.pba('[en]')
317318
' lang="en"'
318319
319-
>>> rt.pba('(#id)')
320+
>>> Py3 << rt.pba('(#id)')
320321
''
321322
322323
"""
@@ -434,7 +435,7 @@ def hasRawText(self, text):
434435
def table(self, text):
435436
r"""
436437
>>> t = Textile()
437-
>>> t.table('(rowclass). |one|two|three|\n|a|b|c|')
438+
>>> Py3 << t.table('(rowclass). |one|two|three|\n|a|b|c|')
438439
'\t<table>\n\t\t<tr class="rowclass">\n\t\t\t<td>one</td>\n\t\t\t<td>two</td>\n\t\t\t<td>three</td>\n\t\t</tr>\n\t\t<tr>\n\t\t\t<td>a</td>\n\t\t\t<td>b</td>\n\t\t\t<td>c</td>\n\t\t</tr>\n\t</table>\n\n'
439440
"""
440441
text = text + "\n\n"
@@ -578,12 +579,12 @@ def fTable(self, match):
578579
def lists(self, text):
579580
"""
580581
>>> t = Textile()
581-
>>> t.lists("* one\\n* two\\n* three")
582+
>>> Py3 << t.lists("* one\\n* two\\n* three")
582583
'\\t<ul>\\n\\t\\t<li>one</li>\\n\\t\\t<li>two</li>\\n\\t\\t<li>three</li>\\n\\t</ul>'
583584
"""
584585

585586
#Replace line-initial bullets with asterisks
586-
bullet_pattern = re.compile(u'^•', re.U | re.M)
587+
bullet_pattern = re.compile('^•', re.U | re.M)
587588

588589
pattern = re.compile(r'^((?:[*;:]+|[*;:#]*#(?:_|\d+)?)%s[ .].*)$(?![^#*;:])'
589590
% self.csl_re_s, re.U | re.M | re.S)
@@ -719,7 +720,7 @@ def doBr(self, match):
719720
def block(self, text, head_offset=0):
720721
"""
721722
>>> t = Textile()
722-
>>> t.block('h1. foobar baby')
723+
>>> Py3 << t.block('h1. foobar baby')
723724
'\\t<h1>foobar baby</h1>'
724725
"""
725726
if not self.lite:
@@ -794,16 +795,16 @@ def block(self, text, head_offset=0):
794795
def fBlock(self, tag, atts, ext, cite, content):
795796
"""
796797
>>> t = Textile()
797-
>>> t.fBlock("bq", "", None, "", "Hello BlockQuote")
798+
>>> Py3 << t.fBlock("bq", "", None, "", "Hello BlockQuote")
798799
('\\t<blockquote>\\n', '\\t\\t<p>', 'Hello BlockQuote', '</p>', '\\n\\t</blockquote>', False)
799800
800-
>>> t.fBlock("bq", "", None, "http://google.com", "Hello BlockQuote")
801+
>>> Py3 << t.fBlock("bq", "", None, "http://google.com", "Hello BlockQuote")
801802
('\\t<blockquote cite="http://google.com">\\n', '\\t\\t<p>', 'Hello BlockQuote', '</p>', '\\n\\t</blockquote>', False)
802803
803-
>>> t.fBlock("bc", "", None, "", 'printf "Hello, World";') # doctest: +ELLIPSIS
804+
>>> Py3 << t.fBlock("bc", "", None, "", 'printf "Hello, World";') # doctest: +ELLIPSIS
804805
('<pre>', '<code>', ..., '</code>', '</pre>', False)
805806
806-
>>> t.fBlock("h1", "", None, "", "foobar")
807+
>>> Py3 << t.fBlock("h1", "", None, "", "foobar")
807808
('', '\\t<h1>', 'foobar', '</h1>', '', False)
808809
"""
809810
att = atts
@@ -911,7 +912,7 @@ def formatFootnote(self, marker, atts='', anchor=True):
911912
def footnoteRef(self, text):
912913
"""
913914
>>> t = Textile()
914-
>>> t.footnoteRef('foo[1] ') # doctest: +ELLIPSIS
915+
>>> Py3 << t.footnoteRef('foo[1] ') # doctest: +ELLIPSIS
915916
'foo<sup class="footnote" id="fnrev..."><a href="#fn...">1</a></sup> '
916917
"""
917918
return re.compile(r'(?<=\S)\[(\d+)(!?)\](\s)?', re.U).sub(
@@ -954,22 +955,22 @@ def glyphs(self, text):
954955
955956
>>> t = Textile()
956957
957-
>>> t.glyphs("apostrophe's")
958+
>>> Py3 << t.glyphs("apostrophe's")
958959
'apostrophe&#8217;s'
959960
960-
>>> t.glyphs("back in '88")
961+
>>> Py3 << t.glyphs("back in '88")
961962
'back in &#8217;88'
962963
963-
>>> t.glyphs('foo ...')
964+
>>> Py3 << t.glyphs('foo ...')
964965
'foo &#8230;'
965966
966-
>>> t.glyphs('--')
967+
>>> Py3 << t.glyphs('--')
967968
'&#8212;'
968969
969-
>>> t.glyphs('FooBar[tm]')
970+
>>> Py3 << t.glyphs('FooBar[tm]')
970971
'FooBar&#8482;'
971972
972-
>>> t.glyphs("<p><cite>Cat's Cradle</cite> by Vonnegut</p>")
973+
>>> Py3 << t.glyphs("<p><cite>Cat's Cradle</cite> by Vonnegut</p>")
973974
'<p><cite>Cat&#8217;s Cradle</cite> by Vonnegut</p>'
974975
975976
"""
@@ -993,9 +994,9 @@ def getRefs(self, text):
993994
Capture and store URL references in self.urlrefs.
994995
995996
>>> t = Textile()
996-
>>> t.getRefs("some text [Google]http://www.google.com")
997+
>>> Py3 << t.getRefs("some text [Google]http://www.google.com")
997998
'some text '
998-
>>> t.urlrefs
999+
>>> Py3 << t.urlrefs
9991000
{'Google': 'http://www.google.com'}
10001001
10011002
"""
@@ -1029,10 +1030,10 @@ def isRelURL(self, url):
10291030
def relURL(self, url):
10301031
"""
10311032
>>> t = Textile()
1032-
>>> t.relURL("http://www.google.com/")
1033+
>>> Py3 << t.relURL("http://www.google.com/")
10331034
'http://www.google.com/'
10341035
>>> t.restricted = True
1035-
>>> t.relURL("gopher://gopher.com/")
1036+
>>> Py3 << t.relURL("gopher://gopher.com/")
10361037
'#'
10371038
10381039
"""
@@ -1050,7 +1051,7 @@ def retrieve(self, text):
10501051
"""
10511052
>>> t = Textile()
10521053
>>> id = t.shelve("foobar")
1053-
>>> t.retrieve(id)
1054+
>>> Py3 << t.retrieve(id)
10541055
'foobar'
10551056
"""
10561057
while True:
@@ -1064,7 +1065,7 @@ def retrieve(self, text):
10641065
def encode_html(self, text, quotes=True):
10651066
"""Return text that's safe for an HTML attribute.
10661067
>>> t = Textile()
1067-
>>> t.encode_html('this is a "test" of text that\\\'s safe to put in an <html> attribute.')
1068+
>>> Py3 << t.encode_html('this is a "test" of text that\\\'s safe to put in an <html> attribute.')
10681069
'this is a &#34;test&#34; of text that&#39;s safe to put in an &lt;html&gt; attribute.'
10691070
"""
10701071
a = (
@@ -1111,7 +1112,7 @@ def graf(self, text):
11111112
def autoLink(self, text):
11121113
"""
11131114
>>> t = Textile()
1114-
>>> t.autoLink("http://www.ya.ru")
1115+
>>> Py3 << t.autoLink("http://www.ya.ru")
11151116
'"$":http://www.ya.ru'
11161117
"""
11171118

@@ -1122,7 +1123,7 @@ def autoLink(self, text):
11221123
def links(self, text):
11231124
"""
11241125
>>> t = Textile()
1125-
>>> t.links('fooobar "Google":http://google.com/foobar/ and hello world "flickr":http://flickr.com/photos/jsamsa/ ') # doctest: +ELLIPSIS
1126+
>>> Py3 << t.links('fooobar "Google":http://google.com/foobar/ and hello world "flickr":http://flickr.com/photos/jsamsa/ ') # doctest: +ELLIPSIS
11261127
'fooobar ... and hello world ...'
11271128
"""
11281129

@@ -1223,10 +1224,10 @@ def encode_url(self, url):
12231224
host = netloc_parsed['host']
12241225
port = netloc_parsed['port'] and netloc_parsed['port']
12251226
path = '/'.join( # could be encoded slashes!
1226-
quote(unquote(pce).encode('utf8'), '')
1227+
quote(unquote(pce).encode('utf8'), b'')
12271228
for pce in parsed.path.split('/')
12281229
)
1229-
query = quote(unquote(parsed.query), '=&?/')
1230+
query = quote(unquote(parsed.query), b'=&?/')
12301231
fragment = quote(unquote(parsed.fragment))
12311232

12321233
# put it back together
@@ -1244,7 +1245,7 @@ def encode_url(self, url):
12441245
def span(self, text):
12451246
"""
12461247
>>> t = Textile()
1247-
>>> t.span(r"hello %(bob)span *strong* and **bold**% goodbye")
1248+
>>> Py3 << t.span(r"hello %(bob)span *strong* and **bold**% goodbye")
12481249
'hello <span class="bob">span <strong>strong</strong> and <b>bold</b></span> goodbye'
12491250
"""
12501251
qtags = (r'\*\*', r'\*', r'\?\?', r'\-', r'__',
@@ -1295,9 +1296,9 @@ def fSpan(self, match):
12951296
def image(self, text):
12961297
"""
12971298
>>> t = Textile()
1298-
>>> t.image('!/imgs/myphoto.jpg!:http://jsamsa.com')
1299+
>>> Py3 << t.image('!/imgs/myphoto.jpg!:http://jsamsa.com')
12991300
'<a href="http://jsamsa.com" class="img"><img alt="" src="/imgs/myphoto.jpg" /></a>'
1300-
>>> t.image('!</imgs/myphoto.jpg!')
1301+
>>> Py3 << t.image('!</imgs/myphoto.jpg!')
13011302
'<img align="left" alt="" src="/imgs/myphoto.jpg" />'
13021303
"""
13031304
pattern = re.compile(r"""
@@ -1521,7 +1522,7 @@ def fNoteLists(self, match):
15211522
content = info['def']['content']
15221523
li = """\t<li%s>%s</li>""" % (atts, content)
15231524
o.append(li)
1524-
self.notelist_cache[index] = u"\n".join(o)
1525+
self.notelist_cache[index] = "\n".join(o)
15251526
result = self.notelist_cache[index]
15261527
if result:
15271528
list_atts = self.pba(att)
@@ -1665,3 +1666,13 @@ def textile_restricted(text, lite=True, noimage=True, html_type='xhtml',
16651666
return Textile(restricted=True, lite=lite, noimage=noimage,
16661667
auto_link=auto_link, html_type=html_type).parse( text,
16671668
rel='nofollow')
1669+
1670+
1671+
def setup_module(mod):
1672+
"""Inject Py3 to builtins for doctests."""
1673+
try:
1674+
import builtins
1675+
except ImportError:
1676+
import __builtin__ as builtins
1677+
from textile.tools.doctest_utils import Py3
1678+
builtins.Py3 = Py3

0 commit comments

Comments
 (0)