From 28ad788b4760b81c3e573dc2252854eb57da405a Mon Sep 17 00:00:00 2001 From: Hynek Schlawack Date: Fri, 12 Feb 2016 14:01:56 +0100 Subject: [PATCH] Sort of port to Python 3 --- .gitignore | 3 ++ .travis.yml | 32 ++++++++++++++++ docstring_wrap.py | 53 ++++++++++++++++++++------- test_docstring_wrap.py | 83 ++++++++++++++++++++++++++++++++++++++++++ tox.ini | 9 +++++ 5 files changed, 167 insertions(+), 13 deletions(-) create mode 100644 .gitignore create mode 100644 .travis.yml create mode 100644 test_docstring_wrap.py create mode 100644 tox.ini diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6ac3e6b --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*.pyc +.tox +__pycache__ diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..3a4bf47 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,32 @@ +sudo: false +cache: + directories: + - $HOME/.cache/pip + +language: python + + +matrix: + include: + - python: "2.6" # these are just to make travis's UI a bit prettier + env: TOXENV=py26 + - python: "2.7" + env: TOXENV=py27 + - python: "3.3" + env: TOXENV=py33 + - python: "3.4" + env: TOXENV=py34 + - python: "3.5" + env: TOXENV=py35 + + +install: + - pip install tox + + +script: + - tox + + +notifications: + email: false diff --git a/docstring_wrap.py b/docstring_wrap.py index 1bd4dff..e7b4291 100644 --- a/docstring_wrap.py +++ b/docstring_wrap.py @@ -16,14 +16,34 @@ for most Python projects. from __future__ import unicode_literals +import argparse +import sys import re + +try: + from cStringIO import StringIO +except ImportError: + from io import StringIO from uuid import uuid4 + __all__ = [ "wrapPythonDocstring" ] +if sys.version_info[0] <= 2: + makeID = lambda: unicode(uuid4()) + fromStdin = lambda s: s.decode("utf-8") + toStdout = lambda s: s.encode("utf-8") + PY2 = True +else: + makeID = lambda: str(uuid4()) + fromStdin = lambda s: s + toStdout = lambda s: s + PY2 = False + + def isUnderline(expr): return bool(re.match("[=]+$", expr) or re.match("[-]+$", expr)) @@ -44,7 +64,7 @@ def isAcronym(word): parenthetically (e.g. this one). """ word = word.strip("(") - return ((len(word) > 2 and word[1::2] == '.' * (len(word) / 2)) or + return ((len(word) > 2 and word[1::2] == '.' * int(len(word) / 2)) or word in ["cf.", "viz."]) @@ -390,7 +410,7 @@ class PointTracker(object): def __init__(self, point): self.point = point - self.marker = "{" + unicode(uuid4()) + "}" + self.marker = "{" + makeID() + "}" self.outPoints = [] @@ -525,12 +545,7 @@ def sampleDocstring(): """ - - -if __name__ == '__main__': - import sys - import argparse - +def main(argv, indata): parser = argparse.ArgumentParser() parser.add_argument("--offset", type = int) parser.add_argument("--indent", type = int) @@ -541,7 +556,6 @@ if __name__ == '__main__': from io import StringIO io = StringIO() - indata = sys.stdin.read().decode("utf-8") inlines = indata.split("\n") if namespace.linewise: inlines.insert(0, "") @@ -561,12 +575,25 @@ if __name__ == '__main__': point=point, initialBlank=initialBlank, ) + prefix = StringIO() if namespace.offset is not None: - sys.stdout.write(repr(offset)) - sys.stdout.write(" ") + prefix.write(repr(offset)) + prefix.write(" ") - output = io.getvalue() + output = prefix.getvalue() + io.getvalue() if namespace.linewise: output = "\n".join(output.split("\n")[1:-1]) - sys.stdout.write(output.encode("utf-8")) + return output + + +if __name__ == '__main__': + sys.stdout.write( + toStdout( + main( + sys.argv, + fromStdin(sys.stdin.read()), + ) + ) + ) + sys.stdout.flush() diff --git a/test_docstring_wrap.py b/test_docstring_wrap.py new file mode 100644 index 0000000..f69a7c3 --- /dev/null +++ b/test_docstring_wrap.py @@ -0,0 +1,83 @@ +# Copyright (C) 2012 +# See LICENSE.txt for details. + +""" +Tests for docstring_wrap.py. +""" + +try: + # For Python 2.6 + import unittest2 as unittest +except ImportError: + import unittest + +from docstring_wrap import main, wrapPythonDocstring + + +class FunctionalTests(unittest.TestCase): + """ + Functional tests for the wrapper. + """ + def test_self(self): + """ + This module's, class's, & method's docstrings are fine and therefore + not mangled. They're all interesting because they have different + indentations. + """ + for ds in (__doc__, self.__class__.__doc__, self.test_self.__doc__): + self.assertEqual( + ds, + main(["test"], ds) + ) + + def test_epytext_nop(self): + """ + wrapPythonDocstring has an impressive multi-paragraph docstring full of + epytext and doesn't get mangled. + """ + self.assertEqual( + wrapPythonDocstring.__doc__, + main(["test"], wrapPythonDocstring.__doc__) + ) + + @unittest.expectedFailure + def test_sphinx_nop(self): + """ + Long and Sphinx- (and docstring!)-rich docstrings don't get mangled. + """ + ds = \ + """ + Phasellus purus. + + :param int arg: Cras placerat accumsan nulla. + + >>> print("hello") + hello + + Aliquam erat volutpat. Nunc eleifend leo vitae magna. In id erat non orci + commodo lobortis. Proin neque massa, cursus ut, gravida ut, lobortis eget, + lacus. Sed diam. Praesent fermentum tempor tellus. Nullam tempus. + """ + self.assertEqual( + ds, + main(["test"], ds) + ) + + def test_single_line_too_wide(self): + """ + Overly long single line docstrings get refilled correctly. + """ + ds = """ + This is totally too long and must be refilled. Fortunately we have an awesome plugin for that! + """ # noqa + self.assertEqual( + """ + This is totally too long and must be refilled. Fortunately we have an + awesome plugin for that! + """, + main(["test"], ds) + ) + + +if __name__ == '__main__': + unittest.main() diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..fab2998 --- /dev/null +++ b/tox.ini @@ -0,0 +1,9 @@ +[tox] +envlist = py26,py27,py33,py34,py35 +skipsdist = true + + +[testenv] +commands = python test_docstring_wrap.py +deps = + py26: unittest2 \ No newline at end of file