Skip to content

Commit 8b8d973

Browse files
committed
Merge branch 'release/3.0.0'
2 parents 713b83a + 0ca140f commit 8b8d973

File tree

15 files changed

+118
-78
lines changed

15 files changed

+118
-78
lines changed

.travis.yml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@ env:
33
- REQUIREMENTS=true
44
- REQUIREMENTS=false
55
python:
6-
- "2.6"
76
- "2.7"
8-
- "3.2"
97
- "3.3"
108
- "3.4"
119
- "3.5"
@@ -14,7 +12,6 @@ python:
1412
# command to install dependencies
1513
install:
1614
- if [[ $REQUIREMENTS == true ]] ; then pip install -r requirements.txt ; fi
17-
- if [[ $TRAVIS_PYTHON_VERSION == '3.2' ]] ; then pip install coverage==3.7.1; fi
1815
- pip install coveralls pytest pytest-cov coverage codecov
1916
- pip install -e .
2017
- if [[ ! $TRAVIS_PYTHON_VERSION == 'pypy-5.4' ]] ; then pip install regex; fi

CHANGELOG.textile

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
h1. Textile Changelog
22

3+
h2. Version 3.0.0
4+
* Drop support for Python 2.6 and 3.2.
5+
* Update to the current version of html5lib
6+
* Bugfixes:
7+
** Fix handling of HTML entities in extended pre blocks. ("#55":https://github.com/textile/python-textile/issues/55)
8+
** Empty definitions in definition lists raised an exception ("#56":https://github.com/textile/python-textile/issues/56)
9+
** Fix handling of unicode in img attributes ("#58":https://github.com/textile/python-textile/issues/58)
10+
311
h2. Version 2.3.16
412
* Bugfixes:
513
** Fix processing of extended code blocks ("#50":https://github.com/textile/python-textile/issues/50)

README.textile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,4 @@ bc.. import textile
3939

4040
h3. Notes:
4141

42-
* Active development supports Python 2.6 or later (including Python 3.2+).
42+
* Active development supports Python 2.7 or later (including Python 3.3+).

requirements.txt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1-
html5lib==0.999
2-
Pillow==3.0.0
1+
html5lib>=1.0b10
2+
Pillow==3.0.0
3+
regex

setup.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,15 @@ def get_version():
5555
'Programming Language :: Python :: 3.6',
5656
],
5757
keywords='textile,text,html markup',
58-
install_requires=['six',],
58+
install_requires=[
59+
'six',
60+
'html5lib>=0.999999999',
61+
],
5962
extras_require={
6063
':python_version=="2.6"': ['ordereddict>=1.1'],
61-
'develop': ['regex', 'pytest', 'pytest-cov'],
64+
'develop': ['pytest', 'pytest-cov'],
65+
'imagesize': ['Pillow>=3.0.0'],
66+
'regex': ['regex'],
6267
},
6368
entry_points={'console_scripts': ['pytextile=textile.__main__:main']},
6469
setup_requires=['pytest-runner'],

tests/fixtures/README.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,5 +42,5 @@
4242
<h3>Notes:</h3>
4343

4444
<ul>
45-
<li>Active development supports Python 2.6 or later (including Python 3.2+).</li>
45+
<li>Active development supports Python 2.7 or later (including Python 3.3+).</li>
4646
</ul>

tests/test_github_issues.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,11 @@ def test_github_issue_30():
8686
expect = '\t<p><a href="http://lala.com" title="Tëxtíle">Tëxtíle</a></p>'
8787
assert result == expect
8888

89+
text ='!http://lala.com/lol.gif(♡ imáges)!'
90+
result = textile.textile(text)
91+
expect = '\t<p><img alt="♡ imáges" src="http://lala.com/lol.gif" title="♡ imáges" /></p>'
92+
assert result == expect
93+
8994
def test_github_issue_36():
9095
text = '"Chögyam Trungpa":https://www.google.com/search?q=Chögyam+Trungpa'
9196
result = textile.textile(text)
@@ -199,3 +204,61 @@ def test_github_issue_52():
199204
'</td>\n\t\t\t<td style="text-align:center;">Second Header </td>'
200205
'\n\t\t</tr>\n\t</table>')
201206
assert result == expect
207+
208+
def test_github_issue_55():
209+
"""Incorrect handling of quote entities in extended pre block"""
210+
test = ('pre.. this is the first line\n\nbut "quotes" in an extended pre '
211+
'block need to be handled properly.')
212+
result = textile.textile(test)
213+
expect = ('<pre>this is the first line\n\nbut &quot;quotes&quot; in an '
214+
'extended pre block need to be handled properly.</pre>')
215+
assert result == expect
216+
217+
# supplied input
218+
test = ('pre.. import org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;'
219+
'\nimport ru.onyma.job.Context;\nimport ru.onyma.job.'
220+
'RescheduleTask;\n\nimport java.util.concurrent.'
221+
'ScheduledExecutorService;\nimport java.util.concurrent.TimeUnit;'
222+
'\n\n/**\n* @author ustits\n*/\npublic abstract class '
223+
'MainService<T> extends RescheduleTask implements Context<T> {\n\n'
224+
'private static final Logger log = LoggerFactory.getLogger('
225+
'MainService.class);\nprivate final ScheduledExecutorService '
226+
'scheduler;\n\nprivate boolean isFirstRun = true;\nprivate T '
227+
'configs;\n\npublic MainService(final ScheduledExecutorService '
228+
'scheduler) {\nsuper(scheduler);\nthis.scheduler = scheduler;\n}\n'
229+
'\n@Override\npublic void setConfig(final T configs) {\nthis.'
230+
'configs = configs;\nif (isFirstRun) {\nscheduler.schedule(this, '
231+
'0, TimeUnit.SECONDS);\nisFirstRun = false;\n}\n}\n\n@Override\n'
232+
'public void stop() {\nsuper.stop();\nscheduler.shutdown();\ntry {'
233+
'\nscheduler.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);\n} '
234+
'catch (InterruptedException ie) {\nlog.warn("Unable to wait for '
235+
'syncs termination", ie);\nThread.currentThread().interrupt();\n}'
236+
'\n}\n\nprotected final T getConfigs() {\nreturn configs;\n}\n}')
237+
result = textile.textile(test)
238+
expect = ('<pre>import org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;'
239+
'\nimport ru.onyma.job.Context;\nimport ru.onyma.job.'
240+
'RescheduleTask;\n\nimport java.util.concurrent.'
241+
'ScheduledExecutorService;\nimport java.util.concurrent.'
242+
'TimeUnit;\n\n/**\n* @author ustits\n*/\npublic abstract class '
243+
'MainService&lt;T&gt; extends RescheduleTask implements '
244+
'Context&lt;T&gt; {\n\nprivate static final Logger log = '
245+
'LoggerFactory.getLogger(MainService.class);\nprivate final '
246+
'ScheduledExecutorService scheduler;\n\nprivate boolean '
247+
'isFirstRun = true;\nprivate T configs;\n\npublic MainService('
248+
'final ScheduledExecutorService scheduler) {\nsuper(scheduler);'
249+
'\nthis.scheduler = scheduler;\n}\n\n@Override\npublic void '
250+
'setConfig(final T configs) {\nthis.configs = configs;\nif ('
251+
'isFirstRun) {\nscheduler.schedule(this, 0, TimeUnit.SECONDS);'
252+
'\nisFirstRun = false;\n}\n}\n\n@Override\npublic void stop() {'
253+
'\nsuper.stop();\nscheduler.shutdown();\ntry {\nscheduler.'
254+
'awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);\n} catch '
255+
'(InterruptedException ie) {\nlog.warn(&quot;Unable to wait '
256+
'for syncs termination&quot;, ie);\nThread.currentThread().'
257+
'interrupt();\n}\n}\n\nprotected final T getConfigs() {\n'
258+
'return configs;\n}\n}</pre>')
259+
assert result == expect
260+
261+
def test_issue_56():
262+
result = textile.textile("- :=\n-")
263+
expect = '<dl>\n</dl>'
264+
assert result == expect

tests/test_textile.py

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -67,22 +67,18 @@ def test_autolinking():
6767
def test_sanitize():
6868
test = "a paragraph of benign text"
6969
result = "\t<p>a paragraph of benign text</p>"
70-
try:
71-
expect = textile.Textile().parse(test, sanitize=True)
72-
assert result == expect
73-
74-
test = """<p style="width: expression(alert('evil'));">a paragraph of evil text</p>"""
75-
result = '<p style="">a paragraph of evil text</p>'
76-
expect = textile.Textile().parse(test, sanitize=True)
77-
assert result == expect
78-
79-
test = """<p>a paragraph of benign text<br />and more text</p>"""
80-
result = '<p>a paragraph of benign text<br />\nand more text</p>'
81-
expect = textile.Textile(html_type='html5').parse(test, sanitize=True)
82-
assert result == expect
83-
except Exception as e:
84-
message = '{0}'.format(e)
85-
assert "html5lib not available" in message
70+
expect = textile.Textile().parse(test, sanitize=True)
71+
assert result == expect
72+
73+
test = """<p style="width: expression(alert('evil'));">a paragraph of evil text</p>"""
74+
result = '<p style="">a paragraph of evil text</p>'
75+
expect = textile.Textile().parse(test, sanitize=True)
76+
assert result == expect
77+
78+
test = """<p>a paragraph of benign text<br />and more text</p>"""
79+
result = '<p>a paragraph of benign text<br />\nand more text</p>'
80+
expect = textile.Textile(html_type='html5').parse(test, sanitize=True)
81+
assert result == expect
8682

8783
def test_imagesize():
8884
PIL = pytest.importorskip('PIL')

textile/__init__.py

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,3 @@
99
__all__ = ['textile', 'textile_restricted']
1010

1111
__version__ = VERSION
12-
13-
14-
if sys.version_info[:2] == (2, 6):
15-
warnings.warn(
16-
"Python 2.6 is no longer supported by the Python core team, please "
17-
"upgrade your Python. A future version of textile will drop support "
18-
"for Python 2.6",
19-
DeprecationWarning
20-
)

textile/core.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,7 @@
3232
from textile.objects import Block, Table
3333

3434

35-
try:
36-
from collections import OrderedDict
37-
except ImportError:
38-
from ordereddict import OrderedDict
35+
from collections import OrderedDict
3936

4037

4138
try:
@@ -506,7 +503,10 @@ def block(self, text):
506503
block.outer_atts)
507504
line = "\t{0}".format(line)
508505
else:
509-
line = self.graf(line)
506+
if block.tag == 'pre':
507+
line = self.shelve(encode_html(line, quotes=True))
508+
else:
509+
line = self.graf(line)
510510

511511
line = self.doPBr(line)
512512
line = line.replace('<br>', '<br />')
@@ -1184,6 +1184,8 @@ def fRCList(self, match):
11841184
# parse the attributes and content
11851185
m = re.match(r'^[-]+({0})[ .](.*)$'.format(cls_re_s), line,
11861186
flags=re.M | re.S)
1187+
if not m:
1188+
continue
11871189

11881190
atts, content = m.groups()
11891191
# cleanup

0 commit comments

Comments
 (0)