11# -*- coding: utf-8 -*-
22""" Tests for the trait documenter. """
33
4-
4+ import contextlib
5+ import io
6+ import os
7+ import shutil
8+ import tempfile
59import textwrap
610import tokenize
711import unittest
12+ try :
13+ # Python 3: mock in the standard library.
14+ import unittest .mock as mock
15+ except ImportError :
16+ # Python 2: need to use 3rd-party mock.
17+ import mock
818
919import six
10- if six .PY2 :
11- import mock
12- else :
13- import unittest .mock as mock
1420
21+ try :
22+ import sphinx # noqa: F401
23+ except ImportError :
24+ sphinx_available = False
25+ else :
26+ sphinx_available = True
1527
16- def _sphinx_present ():
17- try :
18- import sphinx # noqa
19- except ImportError :
20- return False
28+ from traits .api import HasTraits , Int
2129
22- return True
30+ if sphinx_available :
31+ from sphinx .ext .autodoc import Options
32+ from sphinx .ext .autodoc .directive import DocumenterBridge
33+ from sphinx .testing .path import path
34+ from sphinx .testing .util import SphinxTestApp
35+ from sphinx .util .docutils import LoggingReporter
2336
37+ from traits .util .trait_documenter import (
38+ _get_definition_tokens ,
39+ TraitDocumenter ,
40+ )
2441
25- @unittest .skipIf (
26- not _sphinx_present (), "Sphinx not available. Cannot test documenter"
42+ skip_unless_sphinx_present = unittest .skipUnless (
43+ sphinx_available ,
44+ "Sphinx is not available. Cannot test documenter." ,
2745)
46+
47+
48+ class MyTestClass (HasTraits ):
49+ """
50+ Class-level docstring.
51+ """
52+ #: I'm a troublesome trait with a long definition.
53+ bar = Int (42 , desc = """ First line
54+
55+ The answer to
56+ Life,
57+ the Universe,
58+
59+ and Everything.
60+ """ )
61+
62+
63+ @skip_unless_sphinx_present
2864class TestTraitDocumenter (unittest .TestCase ):
2965 """ Tests for the trait documenter. """
3066
@@ -38,9 +74,6 @@ def setUp(self):
3874 self .tokens = tokens
3975
4076 def test_get_definition_tokens (self ):
41-
42- from traits .util .trait_documenter import _get_definition_tokens
43-
4477 src = textwrap .dedent (
4578 """\
4679 depth_interval = Property(Tuple(Float, Float),
@@ -59,8 +92,6 @@ def test_get_definition_tokens(self):
5992
6093 def test_add_line (self ):
6194
62- from traits .util .trait_documenter import TraitDocumenter
63-
6495 src = textwrap .dedent (
6596 """\
6697 class Fake(HasTraits):
@@ -87,3 +118,61 @@ class Fake(HasTraits):
87118
88119 self .assertEqual (
89120 len (documenter .directive .result .append .mock_calls ), 1 )
121+
122+ def test_abbreviated_annotations (self ):
123+ # Regression test for enthought/traits#493.
124+ with self .create_test_directive () as directive :
125+ documenter = TraitDocumenter (
126+ directive , __name__ + ".MyTestClass.bar" )
127+ documenter .generate (all_members = True )
128+ result = directive .result
129+
130+ # Find annotations line.
131+ for item in result :
132+ if item .lstrip ().startswith (":annotation:" ):
133+ break
134+ else :
135+ self .fail ("Didn't find the expected trait :annotation:" )
136+
137+ # Annotation should be a single line.
138+ self .assertIn ("First line" , item )
139+ self .assertNotIn ("\n " , item )
140+
141+ @contextlib .contextmanager
142+ def create_test_directive (self ):
143+ """
144+ Helper function to create a a "directive" suitable
145+ for instantiating the TraitDocumenter with, along with resources
146+ to support that directive, and clean up the resources afterwards.
147+
148+ Returns
149+ -------
150+ contextmanager
151+ A context manager that returns a DocumenterBridge instance.
152+ """
153+ with self .tmpdir () as tmpdir :
154+ # The configuration file must exist, but it's okay if it's empty.
155+ conf_file = os .path .join (tmpdir , "conf.py" )
156+ with io .open (conf_file , "w" , encoding = "utf-8" ):
157+ pass
158+
159+ app = SphinxTestApp (srcdir = path (tmpdir ))
160+ app .builder .env .app = app
161+ app .builder .env .temp_data ["docname" ] = "dummy"
162+ yield DocumenterBridge (app .env , LoggingReporter ('' ), Options (), 1 )
163+
164+ @contextlib .contextmanager
165+ def tmpdir (self ):
166+ """
167+ Helper function to create a temporary directory.
168+
169+ Returns
170+ -------
171+ contextmanager
172+ Context manager that returns the path to a temporary directory.
173+ """
174+ tmpdir = tempfile .mkdtemp ()
175+ try :
176+ yield tmpdir
177+ finally :
178+ shutil .rmtree (tmpdir )
0 commit comments