1 """transform.py - create a docutils Document tree from a Package or Module tree
4 :Contact: tibs@tibsnjoan.co.uk
7 :Copyright: This module has been placed in the public domain.
10 __docformat__
= 'reStructuredText'
13 from docutils
.utils
import new_document
14 import docutils
.nodes
as nodes
15 from package
import Package
, NotPython
16 from docutils
.readers
.python
.moduleparser
import Module
, Class
, Docstring
18 def make_document(tree
,settings
=None):
19 """Return a docutils Document tree constructed from this Python tree.
21 The tree given must be either a Package or Module tree.
24 # @@@ Can it ever be anything other than a package or module?
25 # I'd assert not - the module is the basic "smallest unit".
26 # Should we test that?
27 if isinstance(tree
,Package
):
28 document
= new_document("Package %s"%tree
.filename
,settings
)
29 section
= make_package_section(tree
)
31 document
= new_document("Module %s"%os.path
.splitext(tree
.filename
)[0],
33 section
= make_module_section(tree
)
34 document
.append(section
)
37 def make_package_section(tree
,parent_name
=None):
38 """Return a docutils tree constructed from this Package tree
41 tree_name
= "%s.%s"%(parent_name
,tree
.filename
)
43 tree_name
= tree
.filename
44 title
= "Package %s"%(tree_name)
46 # @@@ Do I really want to normalise (case fold, in particular)
47 # the id/name for this section? Python names can legitimately
48 # distinguish case, and whilst that's not terribly useful at
49 # the file level (since not all OS/filesystems keep such a
50 # distinction), it certainly is a valid possibility *within*
53 # make_id() produces a name that starts with [a-z] and continues
54 # with a-z, 0-9 and hyphen (or something like that).
56 # fully_normalize_name() reduces spaces to single spaces (OK),
57 # but also lowercases.
59 # @@@ Think more on usage here, I guess
60 section
= nodes
.section(CLASS
="package",id=nodes
.make_id(title
),
61 name
=nodes
.fully_normalize_name(title
))
62 title
= nodes
.title(text
=title
)
65 # @@@ I'm enforcing an order of modules before non-python files before
68 # - do I want some other way order?
69 # - is this the best way to do it (e.g., I could sort the children
70 # into order first instead)
71 for child
in tree
.children
:
72 if isinstance(child
,Module
):
73 subsection
= make_module_section(child
,tree_name
)
74 section
.append(subsection
)
75 for child
in tree
.children
:
76 if isinstance(child
,NotPython
):
77 subsection
= make_not_python_section(child
,tree_name
)
78 section
.append(subsection
)
79 for child
in tree
.children
:
80 if isinstance(child
,Package
):
81 subsection
= make_package_section(child
,tree_name
)
82 section
.append(subsection
)
85 def make_module_section(tree
,parent_name
=None):
86 """Return a docutils tree constructed from this Module sub-tree
88 module_name
= os
.path
.splitext(tree
.filename
)[0]
90 tree_name
= "%s.%s"%(parent_name
,module_name
)
92 tree_name
= module_name
93 title
= "Module %s"%(tree_name)
95 # @@@ Same considerations on id/name as above
96 section
= nodes
.section(CLASS
="module",id=nodes
.make_id(title
),
97 name
=nodes
.fully_normalize_name(title
))
98 title
= nodes
.title(text
=title
)
101 # Assume that the docstring must be the first child
102 if len(tree
.children
) > 0 and \
103 isinstance(tree
.children
[0],Docstring
):
104 section
.append(make_docstring(tree
.children
[0]))
106 # @@@ Again, I'm looking for classes before anything else
107 for child
in tree
.children
:
108 if isinstance(child
,Class
):
109 subsection
= make_class_section(child
,tree_name
)
110 section
.append(subsection
)
114 def make_not_python_section(tree
,parent_name
=None):
115 """Return a docutils tree constructed from this NotPython (file) sub-tree
118 tree_name
= "%s.%s"%(parent_name
,tree
.filename
)
120 tree_name
= tree
.filename
121 title
= "File %s"%(tree_name)
123 # @@@ Same considerations on id/name as above
124 section
= nodes
.section(CLASS
="file",id=nodes
.make_id(title
),
125 name
=nodes
.fully_normalize_name(title
))
126 title
= nodes
.title(text
=title
)
127 section
.append(title
)
128 paragraph
= nodes
.paragraph(text
="File ")
129 paragraph
.append(nodes
.literal(text
=tree
.filename
))
130 paragraph
.append(nodes
.Text(" is not a Python module."))
131 section
.append(paragraph
)
134 def make_class_section(tree
,parent_name
):
135 """Return a docutils tree constructed from this Class sub-tree
137 tree_name
= "%s.%s"%(parent_name
,tree
.name
)
138 title
= "Class %s"%(tree_name)
140 # @@@ Same considerations on id/name as above
141 section
= nodes
.section(CLASS
="class",id=nodes
.make_id(title
),
142 name
=nodes
.fully_normalize_name(title
))
143 title
= nodes
.title(text
=title
)
144 section
.append(title
)
146 # Assume that the docstring must be the first child
147 if len(tree
.children
) > 0 and \
148 isinstance(tree
.children
[0],Docstring
):
149 section
.append(make_docstring(tree
.children
[0]))
151 # @@@ Don't forget that we want base classes to be named at
156 def make_docstring(docstring
):
157 return nodes
.literal_block(text
=docstring
.text
,CLASS
="docstring")