summaryrefslogtreecommitdiff
path: root/sandbox/tibs
diff options
context:
space:
mode:
Diffstat (limited to 'sandbox/tibs')
-rwxr-xr-xsandbox/tibs/pysource/__init__.py5
-rwxr-xr-xsandbox/tibs/pysource/buildhtml.py354
-rwxr-xr-xsandbox/tibs/pysource/buildtree.py403
-rw-r--r--sandbox/tibs/pysource/doc/readme.rtxt189
-rw-r--r--sandbox/tibs/pysource/doc/whythis.rtxt122
-rw-r--r--sandbox/tibs/pysource/group-notes.txt220
-rwxr-xr-xsandbox/tibs/pysource/html.py1163
-rwxr-xr-xsandbox/tibs/pysource/notes/notes.py115
-rw-r--r--sandbox/tibs/pysource/notes/notes.txt7
-rw-r--r--sandbox/tibs/pysource/notes/roles.txt61
-rw-r--r--sandbox/tibs/pysource/notes/scope.txt19
-rwxr-xr-xsandbox/tibs/pysource/notes/string.html225
-rw-r--r--sandbox/tibs/pysource/notes/thoughts.txt170
-rwxr-xr-xsandbox/tibs/pysource/pysource.py262
-rwxr-xr-xsandbox/tibs/pysource/rjhack.py58
-rw-r--r--sandbox/tibs/pysource/test/readme.txt27
-rw-r--r--sandbox/tibs/pysource/test/test.doctest12
-rwxr-xr-xsandbox/tibs/pysource/test/test.py124
-rw-r--r--sandbox/tibs/pysource/test/test.rtxt442
-rwxr-xr-xsandbox/tibs/pysource/test/testassign.py12
-rwxr-xr-xsandbox/tibs/pysource/test/testfunc.py34
-rwxr-xr-xsandbox/tibs/pysource/test/testinterpreted.py44
-rwxr-xr-xsandbox/tibs/pysource/test/testinterpreted2.py37
-rwxr-xr-xsandbox/tibs/pysource/test/testsimp.py12
-rwxr-xr-xsandbox/tibs/pysource/test/testyield.py8
-rwxr-xr-xsandbox/tibs/pysource/transform.py358
-rwxr-xr-xsandbox/tibs/pysource/utils.py474
-rwxr-xr-xsandbox/tibs/pysource/visit.py2074
-rw-r--r--sandbox/tibs/pysource2/__init__.py10
-rw-r--r--sandbox/tibs/pysource2/log.txt113
-rw-r--r--sandbox/tibs/pysource2/not_a_directory0
-rw-r--r--sandbox/tibs/pysource2/package.py185
-rwxr-xr-xsandbox/tibs/pysource2/pysrc2html.py46
-rw-r--r--sandbox/tibs/pysource2/reader.py31
-rw-r--r--sandbox/tibs/pysource2/temp.rst81
-rw-r--r--sandbox/tibs/pysource2/temp.txt79
-rw-r--r--sandbox/tibs/pysource2/test_package.py179
-rw-r--r--sandbox/tibs/pysource2/test_reader.py127
-rw-r--r--sandbox/tibs/pysource2/transform.py157
-rw-r--r--sandbox/tibs/pysource2/trivial_package/__init__.py2
-rw-r--r--sandbox/tibs/pysource2/trivial_package/file1.py14
-rw-r--r--sandbox/tibs/pysource2/trivial_package/file2.py2
-rw-r--r--sandbox/tibs/pysource2/trivial_package/not_python3
-rw-r--r--sandbox/tibs/pysource2/trivial_package/sub_package/__init__.py0
44 files changed, 0 insertions, 8060 deletions
diff --git a/sandbox/tibs/pysource/__init__.py b/sandbox/tibs/pysource/__init__.py
deleted file mode 100755
index 66239ca01..000000000
--- a/sandbox/tibs/pysource/__init__.py
+++ /dev/null
@@ -1,5 +0,0 @@
-"""Extract information from Python files, for DOCUTILS/reST purposes
-
-:Author: Tibs <tibs@tibsnjoan.co.uk>
-:Version: 0.1
-"""
diff --git a/sandbox/tibs/pysource/buildhtml.py b/sandbox/tibs/pysource/buildhtml.py
deleted file mode 100755
index f620a7a02..000000000
--- a/sandbox/tibs/pysource/buildhtml.py
+++ /dev/null
@@ -1,354 +0,0 @@
-"""Convenience mechanisms for writing HTML
-
-Similar in concept to buildtree.py (qv), but very different in the details.
-"""
-
-import sys
-import string
-
-__docformat__ = "reST"
-
-EMPTY = ["br","hr"]
-"""Elements that do not (may not) have content.
-"""
-
-INLINE = ["em","strong","samp","code","tt","text"]
-"""Elements that may occur 'inline' - within a paragraph, etc.
-
-Note that we include the 'pseudo-element' "text".
-"""
-
-NEWLINE_AFTER = ["html","head","body","table","address"]
-
-LISTS = ["ol","ul","dl"]
-
-
-# ----------------------------------------------------------------------
-class BuildHTML:
-
- def __init__(self,stream=None):
- """Instantiate a BuildHTML instance.
-
- `stream` should be either something that "looks like" a file
- instance (specifically, it has to have a "write" method), or
- else `None` if we want to default to sys.stdout
- """
-
- self.stream = stream or sys.stdout
- self.stack = []
- """A stack of tag names (e.g., ["html","body","h1","p"])
- """
- self.last = None
- """The last element we were told to add to our output.
- """
- self.fancy = 0
-
- def write_doctype(self):
- """Write out the DOCTYPE element at the start of the HTML file.
-
- For the moment, we don't provide any flexibility in this...
- """
- self.stream.write('<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01'
- ' Transitional//EN"'
- ' "http://www.w3.org/TR/html4/loose.dtd">\n')
-
- def finish(self):
- """Call this to indicate we have finished.
-
- It will grumble if anything is left unclosed - i.e., if there
- is still stuff on the internal stack.
- """
- if len(self.stack) > 0:
- raise ValueError,"Items still outstanding on stack: %s"%\
- self._stack_as_string()
-
- def _maybe_write_newline(self,tag,before=1):
- """Decide whether to write a newline before or after an element.
- """
- if before:
- if tag not in INLINE:
- self.stream.write("\n")
- else:
- if tag in NEWLINE_AFTER:
- self.stream.write("\n")
-
- def add(self,tag,*args,**keywords):
- """Write an HTML element at the current level.
-
- For instance::
-
- build.add("em","Some simple text.")
-
- If `tag` is "text" then it will automagically be converted
- to ordinary inline text (even though there is no such HTML
- element).
-
- Otherwise, this produces (for instance)::
-
- <em>Some simple text.</em>
-
- See `write` (which this uses) for more details of the arguments.
- """
- self._maybe_write_newline(tag)
- self.stream.write(self.element(tag,*args,**keywords))
- self.last = "/"+tag
-
- def start(self,tag,*args,**keywords):
- """Write out the start of an HTML element, and start a new level.
-
- `tag` should be the name of an HTML element (a tag), or "comment".
-
- For instance::
-
- build.start("li","some text")
-
- might cause::
-
- <li>some text
-
- to be written out. Note that the element's closing tag is *not*
- written out - see `end()` for that.
-
- If `args` are given, they are assumed to be (things that resolve
- to) more text elements (i.e., strings). For instance::
-
- build.start("li","some text",
- build.element("strong","and emphasis"),
- "and plain text again")
-
- See `write` (which this uses) for more details of the use of the
- `tag` and `keywords` arguments.
- """
- if tag in EMPTY:
- raise ValueError,"Cannot start an 'empty' element (%s)"%tag
- elif tag == "text":
- raise ValueError,"Cannot start 'text'"
- elif tag == "html" and len(self.stack) > 0:
- raise ValueError,\
- "Cannot insert 'html' except at root of stack"
-
- self._maybe_write_newline(tag,before=1)
- self.stream.write(self.start_tag(tag,**keywords))
- content = self._content(tag,args)
- if content:
- self.stream.write(content)
- self._stack_add(tag)
- self.last = tag
-
- def end(self,tag,*args):
- """Write out the end of an HTML element, and finish the current level.
-
- `tag` should be the name of an HTML element (a tag), or "comment".
-
- For instance::
-
- build.end("ul")
-
- Otherwise, for the moment at least, the `tag` being ended
- must be the last tag that was begun (in the future, we *might*
- support automatic "unrolling" of the stack, but not at the
- moment).
-
- NB: if `args` are given, they will also be treated as closing
- tags, in order - thus, for example::
-
- build.end("td","tr","table")
-
- is exactly equivalent to::
-
- build.end("td")
- build.end("tr")
- build.end("table")
-
- (Hmm - I'm not sure if that last is a good idea. Still, I *do*
- use it for that specific instance, which is a relatively common
- thing to want to do, and it does save "wasting" two fairly
- uninteresting lines of code.)
- """
- if tag in EMPTY:
- raise ValueError,"Cannot start an 'empty' element (%s)"%tag
-
- if tag == "text":
- raise ValueError,"Cannot end 'text'"
-
- self._stack_remove(tag)
- self.stream.write(self.end_tag(tag))
- self._maybe_write_newline(tag,before=0)
-
- if args:
- for item in args:
- self.end(item)
- self.last = "/"+args[-1]
- else:
- self.last = "/"+tag
-
- def start_tag(self,tag,**keywords):
- """Construct and return a start tag.
-
- `tag` should be the name of an HTML element (a tag)
-
- `tag` may not be "text".
-
- `keywords` should be attributes for the tag.
- """
- if tag == "comment":
- return "<!-- "
-
- str = "<%s"%tag
- if keywords:
- keys = keywords.keys()
- keys.sort()
- for key in keys:
- value = self.escape(keywords[key])
- str += " %s='%s'"%(key,value)
- return str + ">"
-
- def end_tag(self,tag):
- """Construct and return an end tag.
-
- `tag` should be the name of an HTML element (a tag)
-
- `tag` may not be "text".
- """
- if tag == "comment":
- return " -->"
- else:
- return "</%s>"%tag
-
- def element(self,tag,*args,**keywords):
- """Construct and return a complete HTML element.
-
- `tag` should be the name of an HTML element (a tag), or "text".
-
- If `tag` is "text" then `keywords` is ignored, and the result
- of concatenating `args` is returned.
-
- Otherwise:
-
- - an opening tag is composed from `tag` and `keywords`
- (see `start_tag()`)
- - the result of concatentating `args` is appended to that
- - a closing tag (see `end_tag()`) is appended to that
-
- and the result is returned.
-
- Within `args`, non-strings are coerced to their representations.
- """
- content = self._content(tag,args)
- if tag == "text":
- return content
- else:
- return self.start_tag(tag,**keywords) + content + \
- self.end_tag(tag)
-
-
- def _content(self,tag,args):
- """Return the *content* of an element.
-
- `tag` is not currently used, but *might* be useful later on?
- """
- content = ""
- if args:
- for item in args:
- if type(item) == type(""):
- content += item
- else:
- content += `item`
- return content
-
- def escape(self,text):
- """Return `text` as valid HTML
-
- (that is, with any "special" characters escaped)
- """
- # Hmm - paranoia, just in case
- if type(text) != type(""): return text
-
- text = string.replace(text, "&", "&amp;")
- text = string.replace(text, "<", "&lt;")
- text = string.replace(text, '"', "&quot;")
- text = string.replace(text, ">", "&gt;")
-
- if self.fancy:
- text = string.replace(text, " ", "&deg;")
- text = string.replace(text, "\n", "&para;\n")
- return text
-
- def last_tag(self):
- """Return the last element we were asked to add to our output.
-
- Note that if we just closed element "XX" (for instance), then
- we will return "/XX".
- """
- return self.last
-
- # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- # Stack queries
-
- def _in_list(self):
- """Are we *immediately* within a list
-
- (i.e., the first child element of a list)
- """
- return self.stack[-1] in LISTS
-
-
- # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- # Stack maintenance
-
- def _stack_ends(self,name):
- """Return true if the stack ends with the named entity.
- """
- return self.stack[-1] == name
-
- def _stack_add(self,name):
- """Add a new level to the stack.
- """
- self.stack.append(name)
-
- def _stack_remove(self,name):
- """Remove the last level from the stack
-
- (but only if it is of the right sort).
- """
- if len(self.stack) == 0:
- raise ValueError,"Cannot end %s - nothing outstanding to end"%\
- (name)
- if name != self.stack[-1]:
- raise ValueError,"Cannot end %s - last thing begun was %s"%\
- (name,self.stack[-1])
- del self.stack[-1]
-
- def _stack_as_string(self):
- names = []
- for name in self.stack:
- names.append(name)
- return string.join(names,",")
-
-
-# ----------------------------------------------------------------------
-if __name__ == "__main__":
- build = BuildHTML()
-
- print "Building a page"
- build.start("html")
- build.start("body")
- build.add("h1","Fred")
- build.start("p")
- build.add("text","This is some text.")
- build.add("strong","Really.")
- build.start("p","Another paragraph")
- build.end("body")
- build.end("html")
- build.finish()
-
- print
- print "Building a broken page"
- try:
- build.start("html")
- build.start("body")
- build.add("h1","Fred")
- build.start("p")
- build.finish()
- except ValueError,detail:
- print "ValueError:",detail
diff --git a/sandbox/tibs/pysource/buildtree.py b/sandbox/tibs/pysource/buildtree.py
deleted file mode 100755
index 977226f8d..000000000
--- a/sandbox/tibs/pysource/buildtree.py
+++ /dev/null
@@ -1,403 +0,0 @@
-"""This module explores a different approach to building doctree elements...
-
-The "normal" way of building a DOCUTILS tree involves, well, building a tree
-structure. So one might do::
-
- section = docutils.nodes.section()
- section += docutils.nodes.title(text="Title")
- para = docutils.nodes.paragraph()
- section += para
- para += docutils.nodes.Text("Some ")
- para += docutils.nodes.strong(text="strong text.")
-
-That's all very nice, if one is *thinking* in terms of a tree structure,
-but it is not, for me, a very natural way to construct a text.
-
- (OK - I *know* in practice one would also have imported `paragraph`,
- etc., from `docutils.nodes`, but that is not my point.)
-
-This module allows one to use a more LaTex style of construction, with
-begin and end delimitors for DOCUTILS nodes. Thus the above example becomes::
-
- build.start("section")
- build.add("title","Title")
- build.start("paragraph","Some ")
- build.add("strong","Strong text.")
- build.end("section")
-
-(As a convenience, paragraphs are automatically ended.)
-
-A slightly shorter, and possibly more obfuscated, way of writing this
-would be::
-
- build.start("section",build.make("title","Title")
- build.start("paragraph","Some ",build.make("strong","Strong text."))
- build.end("section")
-
-Sometimes I think that sort of approach makes more sense, sometimes not.
-""" # we need a " to keep [X]Emacs Python mode happy.
-
-import string
-import docutils.nodes
-import docutils.utils
-
-__docformat__ = "reST"
-
-
-# ----------------------------------------------------------------------
-class group(docutils.nodes.Element):
- """Group is a way of grouping together elements.
-
- Compare it to HTML <div> and <span>, or to TeX (?check?)
- \begingroup and \endgroup.
-
- It takes the special attribute `style`, which indicates what
- sort of thing it is grouping - for instance, "docstring" or
- "attributes".
-
- Although it (should be) supplied by the standard DOCUTILS tree,
- reST itself does not use `group`. It is solely used by
- extensions, such as ``pysource``.
-
- In the default HTML Writer, `group` renders invisibly
- (that is, it has no effect at all on the formatted output).
- """
-
- pass
-
-
-# ----------------------------------------------------------------------
-class BuildTree:
-
- def __init__(self, with_groups=1, root=None):
- self.stack = []
- """A stack of tuples of the form ("classname",classinstance).
- """
-
- self.root = root
- """A memory of the first item on the stack (notionally, the
- "document") - we need this because if we `start` a document,
- fill it up, and then `end` it, that final `end` will remove
- the appropriate instance from the stack, leaving no record.
- Thus this is that record.
- """
- if root is not None:
- self._stack_add(root)
-
- self.with_groups = with_groups
-
- def finish(self):
- """Call this to indicate we have finished.
-
- It will grumble if anything is left unclosed, but will
- return the "root" instance of the DOCUTILS tree we've been
- building if all is well...
- """
- if len(self.stack) > 0:
- raise ValueError,"Items still outstanding on stack: %s"%\
- self._stack_as_string()
- else:
- return self.root
-
- def add(self,thing,*args,**keywords):
- """Add a `thing` DOCUTILS node at the current level.
-
- For instance::
-
- build.add("paragraph","Some simple text.")
-
- If `thing` is "text" then it will automagically be converted
- to "Text" (this makes life easier for the user, as all of the
- other DOCUTILS node classes they are likely to use start with a
- lowercase letter, and "Text" is the sole exception).
-
- See `make` (which this uses) for more details of the arguments.
- """
- if thing == "group" and not self.with_groups:
- return
-
- instance = self.make(thing,*args,**keywords)
- self._stack_append(instance)
-
- def addsubtree(self,subtree):
- """Add a DOCUTILS subtree to the current item.
- """
- self._stack_append(subtree)
-
- def current(self):
- """Return the "current" item.
-
- That is, return the item to which `add()` will add DOCUTILS nodes.
- """
- return self._stack_current()
-
- def start(self,thing,*args,**keywords):
- """Add a `thing` DOCUTILS node, starting a new level.
-
- `thing` should be either the name of a docutils.nodes class, or
- else a class itself.
-
- If `thing` is "text" then it will automagically be converted
- to "Text" (this makes life easier for the user, as all of the
- other DOCUTILS node classes they are likely to use start with a
- lowercase letter, and "Text" is the sole exception).
-
- For instance::
-
- build.start("bullet_list")
-
- As a convenience, if `thing` is a paragraph, and if the current
- item is another paragraph, this method will end the old paragraph
- before starting the new.
-
- Note that if `thing` is "document", some extra magic is worked
- internally. If the keywords `warninglevel` and `errorlevel` are
- given, they will be passed to a docutils.utils.Reporter instance,
- as well as being passed down to the `document` class's initialiser.
-
- See `make` (which this uses) for more details of the arguments.
- """
- name = self._nameof(thing)
-
- if name == "group" and not self.with_groups:
- return
-
- if name == "paragraph" and self._stack_ends("paragraph"):
- self.end("paragraph")
-
- if name == "document":
- if self.root:
- return
- if len(self.stack) > 0:
- raise ValueError,\
- "Cannot insert 'document' except at root of stack"
- warninglevel = keywords.get("warninglevel",2)
- errorlevel = keywords.get("errorlevel",4)
- reporter = docutils.utils.Reporter('fubar', warninglevel,
- errorlevel)
- instance = docutils.nodes.document(reporter,"en")
- else:
- instance = self.make(thing,*args,**keywords)
-
- if len(self.stack) == 0:
- self.root = instance
- else:
- self._stack_append(instance)
-
- self._stack_add(instance)
-
- def end(self,thing):
- """End the level started below a `thing` DOCUTILS node.
-
- `thing` should be either the name of a docutils.nodes class, or
- else a class itself.
-
- For instance::
-
- build.end("bullet_list")
-
- As a convenience, if the last item constructed was actually
- a paragraph, and `thing` is the container for said paragraph,
- then the paragraph will be automatically ended.
-
- Otherwise, for the moment at least, the `thing` being ended
- must be the last thing that was begun (in the future, we *might*
- support automatic "unrolling" of the stack, but not at the
- moment).
- """
- name = self._nameof(thing)
-
- if thing == "group" and not self.with_groups:
- return
-
- if self._stack_ends("paragraph") and name != "paragraph":
- self.end("paragraph")
-
- self._stack_remove(name)
-
- def make(self,thing,*args,**keywords):
- """Return an instance of `docutils.nodes.thing`
-
- Attempts to regularise the initialisation of putting initial
- text into an Element and a TextElement...
-
- `thing` should be either the name of a docutils.nodes class, or
- else a class itself (so, for instance, one might call
- ``build.make("paragraph")`` or
- ``build.make(docutils.nodes.paragraph)``),
- or else None.
-
- If `thing` is "text" then it will automagically be converted
- to "Text" (this makes life easier for the user, as all of the
- other DOCUTILS node classes they are likely to use start with a
- lowercase letter, and "Text" is the sole exception).
-
- If `thing` is an Element subclass, then the arguments are just
- passed straight through - any *args list is taken to be children
- for the element (strings are coerced to Text instances), and any
- **keywords are taken as attributes.
-
- If `thing` is an TextElement subclass, then if the first
- item in *args is a string, it is passed down as the `text`
- parameter. Any remaining items from *args are used as child
- nodes, and any **keywords as attributes.
-
- If `thing` is a Text subclass, then a single argument is expected
- within *args, which must be a string, to be used as the Text's
- content.
-
- For instance::
-
- n1 = build.make("paragraph","Some ",
- build.make("emphasis","text"),
- ".",align="center")
- n2 = build.make(None,"Just plain text")
- """
-
- #print "make: %s, %s, %s"%(thing,args,keywords)
-
- # Temporary special case - since group is not (yet) in docutils.nodes...
- if thing == "group":
- thing = group
-
- if thing == None:
- dps_class = docutils.nodes.Text
- elif type(thing) == type(""):
- if thing == "text":
- thing = "Text"
- try:
- dps_class = getattr(docutils.nodes,thing)
- except AttributeError:
- raise ValueError,"docutils.nodes does not define '%s'"%thing
- else:
- dps_class = thing
-
- # NB: check for TextElement before checking for Element,
- # since TextElement is itself a subclass of Element!
- if issubclass(dps_class,docutils.nodes.TextElement):
- # Force the use of the argument list as such, by insisting
- # that the `rawsource` and `text` arguments are empty strings
- args = self._convert_args(args)
- dps_instance = dps_class("","",*args,**keywords)
- elif issubclass(dps_class,docutils.nodes.Element):
- # Force the use of the argument list as such, by insisting
- # that the `rawsource` arguments is an empty string
- args = self._convert_args(args)
- dps_instance = dps_class("",*args,**keywords)
- elif issubclass(dps_class,docutils.nodes.Text):
- if len(args) > 1:
- raise ValueError,\
- "Text subclass %s may only take one argument"%\
- self._nameof(thing)
- elif len(args) == 1:
- text = args[0]
- else:
- text = ""
- if keywords:
- raise ValueError,\
- "Text subclass %s cannot use keyword arguments"%\
- self._nameof(thing)
- dps_instance = dps_class(text)
- else:
- raise ValueError,"%s is not an Element or TextElement"%\
- self._nameof(thing)
-
- #print " ",dps_instance
- return dps_instance
-
- def _convert_args(self,args):
- """Return the arguments, with strings converted to Texts.
- """
- newargs = []
- for arg in args:
- if type(arg) == type(""):
- newargs.append(docutils.nodes.Text(arg))
- else:
- newargs.append(arg)
- return newargs
-
- def __getattr__(self,name):
- """Return an appropriate DOCUTILS class, for instantiation.
- """
- return getattr(docutils.nodes,name)
-
- # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- def _nameof(self,thing):
- if thing is None:
- return "Text"
- elif type(thing) == type(""):
- return thing
- else:
- return thing.__name__
-
- # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- # Stack maintenance
-
- def _stack_ends(self,name):
- """Return true if the stack ends with the named entity.
- """
- return self.stack[-1][0] == name
-
- def _stack_add(self,instance):
- """Add a new level to the stack.
- """
- self.stack.append((instance.__class__.__name__,instance))
-
- def _stack_remove(self,name):
- """Remove the last level from the stack
-
- (but only if it is of the right sort).
- """
- if len(self.stack) == 0:
- raise ValueError,"Cannot end %s - nothing outstanding to end"%\
- (name)
- if name != self.stack[-1][0]:
- raise ValueError,"Cannot end %s - last thing begun was %s"%\
- (name,self.stack[-1][0])
- del self.stack[-1]
-
- def _stack_append(self,instance):
- """Append an instance to the last item on the stack.
- """
- if len(self.stack) > 0:
- self.stack[-1][1].append(instance)
- else:
- raise ValueError,"Cannot add %s to current level" \
- " - nothing current"%(instance.__class__.__name__)
-
- def _stack_current(self):
- """Return the "current" element from the stack
-
- That is, the element to which we would append any new instances
- with `_stack_append()`
- """
- return self.stack[-1][1]
-
- def _stack_as_string(self):
- names = []
- for name,inst in self.stack:
- names.append(name)
- return string.join(names,",")
-
-
-# ----------------------------------------------------------------------
-if __name__ == "__main__":
- build = BuildTree()
- #print build.make("paragraph",text="fred")
- #print build.paragraph(text="fred")
-
- print "Building a section"
- build.start("section")
- build.add("title","Fred")
- build.start("paragraph")
- build.add("text","This is some text.")
- build.add("strong","Really.")
- build.start("paragraph","Another paragraph")
- build.end("section")
- print build.finish()
-
- #print "Building a broken section"
- #build.start("section")
- #build.add("title","Fred")
- #build.start("paragraph")
- #print build.finish()
diff --git a/sandbox/tibs/pysource/doc/readme.rtxt b/sandbox/tibs/pysource/doc/readme.rtxt
deleted file mode 100644
index 5710eaa53..000000000
--- a/sandbox/tibs/pysource/doc/readme.rtxt
+++ /dev/null
@@ -1,189 +0,0 @@
-pysource
-========
-
-:Author: Tibs (tibs@tibsnjoan.co.uk)
-:Date: $Date$
-:Revision: $Revision$
-:Version: 0.1
-
-Ahem
-----
-This file needs updating - unless this notice has disappeared, treat the
-rest of the file as out-of-date...
-
-History
--------
-2002-04:
-
-* Name changed from 'pydps' to 'pysource' (in line with a suggestion
- made a while back on the Doc-SIG by David Goodger).
-
- It's not that that's a great name, just that it's better than 'pydps'
- (especially now that 'dps' has become 'docutils'), and the rather more
- obvious 'pydoc' is already taken. Any suggestions for a better name will
- be gratefully received!
-
-* Converted from the old 'dps' and 'restructuredtext' packages to the
- new 'docutils' package.
-
-* All previous history is elided with the change of name and first release...
-
-Obtaining the package
----------------------
-The latest version of 'pysource' may be found in the Docutils sandbox
-(tarball_ and browsable_).
-
-.. _tarball: http://docutils.sourceforge.net/docutils-sandbox-snapshot.tgz
-.. _browsable: http://docutils.sourceforge.net/sandbox/tibs/pysource/
-
-I hope to keep a copy of the current "released" version at
-
- http://www.tibsnjoan.co.uk/reST/pysource.tgz
-
-Purpose
--------
-This module provides code to
-
- * parse a Python file using the Python Compiler module, which is
- standard with Python 2.2 and later, and available in the Tools
- directory in earlier versions,
- * extract relevant information, including docstrings,
- * and ultimately produce (in the first instance) HTML documentation
- therefrom.
-
-As a subsidiary capability, it can read a restructuredtext file and produce
-HTML from that.
-
-There are obviously other tools which perform similar tasks - see the
-accompanying file whythis.rtxt for some comparisons, and an
-explanation of why I think it is worth developing this tool
-independently.
-
-
-*** TO HERE ***
-
-Usage
------
-The command ``python pysource/pysource.py --help`` gives the following
-information::
-
- """The command line interface to docutil's Python documentation extractor.
-
- Usage: ``pysource.py <switches> <inpath> [<outfile>]``
-
- <inpath> is the path to a package or module.
-
- <outfile> is the path to the output file. If it's not given, then
- output will be written to a file with the same name as the input
- file, but defaulting to the current directory, and with extension
- derived from the type of output:
-
- - show -> ``.show``
- - ast -> ``.ast``
- - xml -> ``.xml``
- - html -> ``.html``
- - pretty -> ``.pretty``
-
- (unless --stdout is requested). The default is --html.
-
- Note that progress messages (and ``verb`` information) are written
- to ``sys.stderr``.
- """
-
- <switches> are:
-
- -v, --verbose Report on progress in more detail
- -q, --quiet Suppress normal progress messages
- -t, --text The input file is a plain (text) reST file
- -s, --show Output basic information about the input
- -a, --ast Output a representation of the AST
- -x, --xml Output an XML representation of the input
- -h, --html Output an HTML representation of the input [default]
- -p, --pretty Output a 'pretty' representation of the input
- -d, --doctest Treat a reST file as doctest input.
- -h, --help Show 'help' information
- -n, --new Use David Goodger's HTML Writer (sort of)
- --stdout Write output to stdout, instead of a file
-
-I recommend use of the ``--pretty`` option for gaining an understanding of the
-DPS tree itself.
-
-Limitations and dependencies
-----------------------------
-This is beta software, and is still, to some extent, a proof and exploration of
-concept.
-
-The following limitations are obvious:
-
- * Its concept of a "package" is rather limited - it doesn't understand
- sub-packages (i.e., it only copes with a "flat" directory structure).
- * It only produces a single HTML file - a more sophisticated approach
- is clearly needed, particularly for large packages (or even large
- modules).
- * It is not fully integrated with the Docutils HTML Writer, which it
- should be using in preference to my own home-grown approach.
- * The Docutils tree that it produces could use some improvement - in
- particular the Python specific nodes need various design decisions
- to be made.
-
-Also:
-
- * It doesn't throw away as much information as it should.
- * It doesn't check all assignments for use of global values.
- * It doesn't handle all Python entities that it should.
- * The HTML it produces is pretty yuck, and is *designed* not
- to look terribly nice (although you should remember not to
- ask my opinion of the HTML output by pydoc).
- * Autonumbered footnote resolution is done by the HTML writer,
- which means that it will likely go wrong if it needs to do
- anything with Python source that contains autonumbered
- footnotes in docstrings(!). But it does work (I believe)
- for .rtxt files.
- * Various other Docutils tree transforms that should be applied
- are not yet performed.
-
-Subtler things:
-
- * The ``--doctest`` mode just pretends that the whole file is
- a single doctest string (i.e., just as if doctest had found
- it as a docstring in a Python file).
-
- That's quite sensible, except that the current doctest doesn't
- know that it should ignore literal blocks, and thus may find
- apparent Python code where it shouldn't.
-
-It depends on:
-
- * The latest versions of Docutils, as of the
- time it was uploaded (I generally track these fairly well,
- so am normally using the latest versions whilst developing).
- These should have been installed (using the setup scripts
- they provide).
- * Python 2.0 or above
- * Tools/compiler for the current Python. For Pythons before
- 2.2a4 (I think it was) this should be installed using the
- setup script it provides (after that it comes as standard).
-
-I develop it with Python 2.1 on Windows/NT and with Python 2.2 on
-Debian GNU/Linux.
-
-Refactoring warning
--------------------
-It is my aim to refactor this code to follow David Goodger's
-
- Reader - Transformer - Writer
-
-model more closely than it currently does. And there is also lots of
-tidying up to do (especially in `visit.py`).
-
-Interesting things to do
-------------------------
-Run it over docutils/spec/reStructuredText.txt.
-
-Run it over docutils/docutils.
-
-Run it over pysource/visit.py.
-
-Run it over the standard string module, and compare the result with that
-of ``pydoc``.
-
diff --git a/sandbox/tibs/pysource/doc/whythis.rtxt b/sandbox/tibs/pysource/doc/whythis.rtxt
deleted file mode 100644
index 0307654a2..000000000
--- a/sandbox/tibs/pysource/doc/whythis.rtxt
+++ /dev/null
@@ -1,122 +0,0 @@
-Why pysource?
-=============
-
-There is the question of why a new tool is needed to go with Docutils and
-reStructuredText, when there are several existing tools which could have been
-adopted.
-
-Perhaps the main reason is simply as a "proof of concept" - even if pysource
-itself is not adopted as *the* tool for use in documenting Python source files
-(and I certainly would not advocate that it be the only one, as other tools
-present their own particular advantages), it *is* worth doing as a "proof of
-concept" - as an examplar that it is possible to do the job.
-
-Three existing tools deserve particular consideration:
-
- - pydoc
- - HappyDoc
- - PyPaSax
-
-pydoc
------
-
-pydoc is Ka-Ping Yee's classic application. It is now (as of Python 2.1)
-included in the standard Python library, where it also provides the backbone
-for the "help" command.
-
-pydoc uses introspection of "live" objects to determine information - that is,
-it requires that the modules to be documented be imported. This can be a
-limiting factor - sometimes it is not advisable to import a module, and
-sometimes it is simply not possible.
-
-It provides output as HTML, and also has a rather output mode for use at
-a terminal.
-
-.. note:
- I've still to work out how to make pydoc work as a standalone tool
- (i.e., at the terminal prompt) for documenting my own Python code
- - for instance, doing ``pydoc.py pysource/visit.py``, which, at best,
- doesn't seem to see any documentation!
-
-HappyDoc
---------
-
- http://happydoc.sourceforge.net/
-
-HappyDoc is a seriously neat tool, and one of the longest standing in the
-arena. It is a mature tool, and:
-
- - supports several forms of structured text within docstrings - notably
- plain text, "raw" text, StructuredTextClassic and StructuredTextNG.
-
- - allows the extraction of documentation from comments as well as from
- docstrings.
-
- - supports several forms of output - notably HTML, SGML and XML DocBook,
- plain text, and Dia files.
-
- - has documented mechanisms for adding new import and export filters.
-
- - has sophisticated control over the actual details of export (HTML options,
- single or multiple files, etc.)
-
-I would expect it to add support for reStructuredText in the near future.
-
-PyPaSax
--------
-
- http://www.logilab.org/pypasax/
-
-PyPaSax is a Python module that uses the python parser to generate Sax2 events,
-and thus enables the visualisation of a python document as an XML tree. This is
-used at Logilab for documenting the source code of Narval. Logilab are also
-working on an XSL transformation to generate XMI from the generated XML, which
-should allow interface to UML tools.
-
-This is a very interesting approach to the problem of extracting information
-from Python modules, but it is currently relatively "coarse grained" - it does
-not, for instance, pay attention to docstrings.
-
-pysource
---------
-
-http://docutils.sourceforge.net/sandbox/pysource/ (or from the tarball_).
-
-.. _tarball: http://docutils.sourceforge.net/docutils-sandbox-snapshot.tgz
-
-pysource is intended as a proof-of-concept implementation of the concepts in
-the Docutils PEPs.
-
-It parses Python files using the Compiler module, honouring the __docformat__
-module value to decide whether docstrings are in reStructuredText or plain
-text.
-
-It uses Docutils to organise the information so gained, and the results of
-parsing the Python code are integrated with the parsed docstring text into a
-single Docutils nodes tree.
-
-The initial version of pysource supports the output of XML (which is a native
-ability of Docutils itself), and HTML. Since it is intended that pysource
-integrate closely with Docutils, additional output formats will occur as new
-Writers are added to Docutils itself.
-
-See also
---------
-pep-0256: Docstring Processing System Framework
-
- This includes a closer analysis of why pydoc is not directly suitable
- for the purposes of Docutils.
-
-pep-0257: Docstring conventions
-
- This describes the high-level structure of docstrings.
-
-pep-0258: Docutils Design Specification
-
- This includes a description of what a tool such as pysource should
- actually do - what docstrings to extract and from where, and how to
- decide what format is used within said docstrings.
-
-pep-0287: reStructuredText Standard Docstring Format
-
- The PEP for reStructuredText itself.
diff --git a/sandbox/tibs/pysource/group-notes.txt b/sandbox/tibs/pysource/group-notes.txt
deleted file mode 100644
index 6c3f281f9..000000000
--- a/sandbox/tibs/pysource/group-notes.txt
+++ /dev/null
@@ -1,220 +0,0 @@
-Adding <group>, losing <package_section> and their ilk
-======================================================
-
-:Author: Tibs
-:Date: 2001-11-18
-
-Background
-----------
-I am currently writing software that will take information from
-Python source files, produce a DPS node tree therefrom, and allow
-the user to generate HTML from that.
-
-My initial implementation produced a *variant* of the DPS node
-tree, which contained many structures that related closely to the
-information derived from Python - for instance, something like::
-
- <py_class name="Fred">
- <docstring>
- This is a very silly class.
- <py_attr_list>
- <py_attr name="jim">
- <py_method "name="method">
-
-For various reasons, the (implicit) DTD wasn't shaping up very
-like that proposed by David Goodger, so I asked about the
-possibility of amending the "standard" DTD. This led to a
-discussion of how the flow of information through a DPS processor
-should actually work, with the result being David's diagram
-[#diagram]_::
-
- +--------+ +--------+ +------------+ +--------+
- | READER | --> | linker | --> | transforms | --> | WRITER |
- +--------+ +--------+ +------------+ +--------+
- | TOC, index, |
- | etc. (optional) |
- +--------+ +--------+
- | PARSER | | filer |
- +--------+ +--------+
-
-David also made the point that, within this plan, the result of
-the ``linker`` phase is a normal DPS tree, which can be
-transformed with any of the "standard" transformation tools (for
-instance, to resolve automatic footnotes), and then output with
-any writer.
-
-Whilst David's diagram is not *quite* how I see the process, it's
-close enough for this purpose. Thus pydps [#pydps]_ might be shown
-as::
-
- +--------+ +--------------+ +------------+ +---------+
- | READER | --> | transform.py | --> | transforms | --> | html.py |
- +--------+ +--------------+ +------------+ +---------+
- | |
- +----------+ +---------------+
- | visit.py | | buildhtml.py |
- +----------+ +---------------+
-
-The "READER" is implicit in the main utility (currently
-``pydps.py``), and locates the relevant Python files. It then
-uses ``visit.py`` to generate a tree representing the Python code
-(the Python ``compiler`` module, standard with Python 2.2 and
-above, but in ``Tools`` before that, is used).
-
-``transform.py`` (which, by David's diagrams, should maybe be
-called ``link``) transforms that information into a proper DPS
-node tree. At the time of writing, no transformations are done.
-
-Finally, HTML is output from the DPS node tree by ``html.py``.
-
-So, in summary:
-
- 1. ``transform.py`` generates a *normal* DPS tree. It doesn't
- use any "odd" nodes (except <group> - but we'll discuss
- that later on). This means that it should be possible to
- plug in any other writer, and produce a different format as
- output - a very significant advantage.
-
- 2. ``html.py`` expects to be given a *normal* DPS tree. This
- means that it should be usable by any other utility that
- also provides a normal DPS tree - again an advantage.
-
-The problem
------------
-But there is a clash in requirements here. Whilst it is very nice
-to be able to represent the Python information as "normal" DPS
-(guaranteeing that anyone can do useful things with it), there is
-some need to transfer information that goes beyond that. There
-are two main reasons for wanting to do this:
-
- * Data mining
- * Presentation
-
-For the first, although DPS/reST/pydps is primarily about
-producing human-viewable documentation, it might also be nice to
-be able to extract parts of it automatically, for various
-purposes - for instance, retrieve just the information about
-which classes inherit from other. This information will, in part,
-be obvious from the text chosen within the document (a title like
-"Class Fred" might be taken to be useful, for instance!), but it
-would be nice to give a bit more help.
-
-For the second, it's relatively difficult to produce better
-layout for DPS Python documentation without more information to
-work on. If one uses the (rather garish) default presentation
-produced by pydps (and no, I'm not saying that's a *nice*
-presentation, but it is the one I've got as an example), it is
-clearly useful to be able to:
-
- 1. group together the package/class/method/etc title and its
- full name/path/whatever
-
- 2. group together a method or function's signature and its
- docstring
-
-David's original approach to this was to introduce a host of
-Python specific tags into ``nodes.py`` [#nodes]_ - for instance::
-
- package_section
- module_section
- ...
- instance_attribute_section
- ...
- parameter_item
- parameter_tuple
- ...
- package
- module
- class_attribute
-
-There are several problems with approach. Perhaps the most
-serious is that *all* generic DPS writers need to understand
-this host of elements that are only relevant to Python. Clearly,
-someone writing a writer for other purposes may be reluctant to
-go to this (to them) redundant effort.
-
-From my point of view, an immediate problem is that the set of
-elements is not *quite* what I want - which means working towards
-a set of patches for ``nodes.py`` and the relevant DTD, and
-getting David to agree to them (well, that last is a useful
-process to have in place, but still). Since I'm not likely to get
-it right immediately, this is a repetitive process.
-
-Lastly, one might imagine someone from another programming
-language domain adopting DPS/reST. One can expect them to be
-frustrated if the set of constructs provided for Python doesn't
-quite match the set of constructs required to describe their
-language in a natural manner.
-
-Luckily (!), I have a counter proposal, which hopefully keeps the
-baby and just loses the bath water.
-
-Groups and "style"
-------------------
-The first thing that I realised was that, for convenience of
-output at least, I wanted to be able to group elements together -
-or, in terms of the DPS tree, insert an arbitrary "subroot"
-within the tree to 'abstract' a branch of the tree.
-
-This is particularly useful for linking together the parts of the
-text that deal with (for instance) attribution, or unusual
-globals, without having to embed yet another section.
-
-There is, of course, precedent. HTML provides <div> and <span> -
-one for "structural" elements, and one for inline elements (I
-forget which is which), and TeX and LaTeX are well-known for
-their use of grouping (e.g., the ``\begin{xxx}`` and
-``\end{xxx}`` in LaTeX).
-
-I don't consider it worth making the <div>/<span> distinction in
-the context of a tree - it is perfectly evident what is beingp
-grouped from the elements themselves.
-
-Once one has a <group> element, it is natural to annotate it with
-*what* it is a group of/for. I chose the arbitrary term "style" -
-partly because it is not used in HTML/XML for any purpose I am
-aware of.
-
-And once one has the "style" attribute, it becomes possible to
-use it elsewhere - most notably in <section> elements, saving the
-need for a myriad of different sections for different purposes.
-
-In these instances, it is perhaps acting more like the "class"
-attribute in HTML - indicating, to some extent, meaning, but
-aimed mostly at presentation (via CSS).
-
-The other obvious place to use it is in the automatically
-generated text for things like names, where (at least
-pre-"combing"/transformation) one is "pretending" to have
-assigned a role (just as a person might in a docstring) (but see
-[#style]_).
-
-Summary
--------
-Current DPS defines many element types for use in Python code
-representation.
-
-However, there are major advantages in only using the "simple"
-DPS nodes for all purposes.
-
-This becomes simple and practical given a single extra, general
-purpose, element: <group>.
-
-Furthermore, adding a standard attribute called "style" (or
-perhaps "role" - see [#style]_) seems to fulfil any other
-outstanding requirements.
-
-References
-----------
-.. [#diagram] in email by David Goodger to Doc-SIG, dated
- 21 September 2001 04:31, "Re: [Doc-SIG] DPS components".
-
-.. [#style] Hmm - maybe "style" should be "role", to match
- with the way that a ``:role:`of something``` gets handled...
-
-.. [#pydps] Normally to be found at
- http://www.tibsnjoan.co.uk/reST/pydps.tgz,
- although note that this is not currently up-to-date.
-
-.. [#nodes] dps/dps/nodes.py in the DPS distribution
- (``dps.nodes`` if one is importing it).
diff --git a/sandbox/tibs/pysource/html.py b/sandbox/tibs/pysource/html.py
deleted file mode 100755
index 398151a0e..000000000
--- a/sandbox/tibs/pysource/html.py
+++ /dev/null
@@ -1,1163 +0,0 @@
-"""Output DOCUTILS nodes as HTML.
-
-This is a quick-and-dirty approach to writing out HTML derived from
-a DOCUTILS node tree. It maintains a minimum of state, and doesn't attempt
-any particular intelligence about the tree structure.
-
- Note: for debugging purposes some HTML elements are output with
- "style" attributes - this is so I can track which elements were
- written for what purpose, and is temporary.
-
- (Use of "class" attributes to make CSS usage easier is a
- separate consideration, to be made later on.)
-
-Use of this should ultimately be replaced by use of David's new mechanisms
-from the docutils module - but they didn't exist when I started, so we'll live
-with this for a little longer.
-"""
-
-import time
-import buildhtml
-
-__docformat__ = "reST"
-
-class HTMLError(Exception):
- pass
-
-
-# ----------------------------------------------------------------------
-class Writer:
- """Encapsulate the HTML writing stuff in a class
-
- - it makes it easier to handle values we want to keep around
- """
-
- colours = {"Information": "#FF0000",
- "Warning" : "#FF0000",
- "Error" : "#FF0000",
- "Fatal" : "#FF0000",
- "WarningBG" : "Silver", # (was "lightgrey" or #DDDDDD)
- "default" : "#FFFFCC",
- }
- """Colours to use to distinguish various contexts
-
- Note that the HTML4 spec defines the following colours:
-
- * Black = "#000000"
- * Silver = "#C0C0C0"
- * Gray = "#808080"
- * White = "#FFFFFF"
- * Maroon = "#800000"
- * Red = "#FF0000"
- * Purple = "#800080"
- * Fuchsia = "#FF00FF"
- * Green = "#008000"
- * Lime = "#00FF00"
- * Olive = "#808000"
- * Yellow = "#FFFF00"
- * Navy = "#000080"
- * Blue = "#0000FF"
- * Teal = "#008080"
- * Aqua = "#00FFFF"
- """ #"
-
- role_text = {"package" : "Package",
- "module" : "Module",
- "class" : "Class",
- "method" : "Method",
- "function" : "Function",
- "module_attribute" : "Module attribute",
- "class_attribute" : "Class attribute",
- "instance_attribute": "Instance attribute",
- "variable" : "Name",
- "parameter" : "Argument",
- "type" : "Type",
- "exception_class" : "Exception class",
- "exception" : "Exception",
- "warning_class" : "Warning class",
- "warning" : "Warning"}
- """If an interpreted text has a role, we want to write that role
- out. We thus need a dictionary to relate role names to the text
- to be written out.
- """
-
- fancy = 0
- """Do we want fancy presentation?"""
-
- want_contents = 0
- """Do we *want* contents for this document?
- """
-
- language = "en"
- """The language that we believe our document to be
- destined for.
- """
-
- showwarnings = 1
- """Should we show warnings, or try to continue silently?
- """
-
- showinforms = 1
- """Should we show informational messages, or ignore them?
- """
-
- visible_targets = 0
- """Show link target names
- """
-
- visible_links = 0
- """Show link references (although not all of the possible links
- we produce).
- """
-
- def __init__(self):
-
- # The current document tree - unset it here just in case...
- self.document = None
-
- # Our HTML builder - ditto
- self.html = None
-
- # Our method cache - we seed it with the entry for "#text"
- # because we can't deduce the method name from that tag
- # ("write_#text" is not a valid Python name!)
- self.method_cache = {"#text":self.write_text}
-
- def __call__(self,document,stream):
- """Output an HTML representation of `document` to `stream`.
-
- Arguments:
-
- * document -- the DOCUTILS tree we are to output as HTML
- * stream -- something like a File, with a write method
- """
-
- self.document = document
- self.html = buildhtml.BuildHTML(stream)
-
- # Reset things (i.e., so we can be called more than once)
-
- # The header level to use for <section> titles
- # (i.e., <h2>, <h3>, etc).
- self.level = 0
-
- # Have we output Contents for this document?
- self.got_contents = 0
-
- # Are we within the body of a field list item?
- self.infield = 0
-
- # Or in a paragraph? (note - only in the sense that the DOCUTILS
- # tree says that we're in a paragraph)
- self.in_paragraph = 0
-
- # Footnote autonumbers
- self.auto_footnote = 0
- """The current auto-numbered footnote's number.
- This will be stored as attribute "auto-index" on
- the footnote itself, by `find_auto_footnotes()`.
- """
- self.auto_footnote_names = {}
- """A dictionary linking an auto-numbered footnote label
- to the corresponding (generated) footnote number. This
- is populated by `find_auto_footnotes()`.
- """
- self.auto_footnote_list = []
- """A list of the auto-numbered footnote numbers that
- are used for non-named footnotes. This list is then
- used to populate the [#]_ footnote references. It is
- populated by `find_auto_footnotes()`.
- """
- self.auto_footnote_index = 0
- """An index into `self.auto_footnote_list`.
- """
- self.auto_footnote_target = 0
- """This is used to record the numbering for the "link" end
- of footnotes - i.e., the number for autonumbered references.
- """
-
- self.find_auto_footnotes(document)
-
- # Table location
- self.in_table_header = 0
- self.in_table_body = 0
-
- # And now down to work...
- self.html.write_doctype()
- self.html.start("html")
-
- # Hmm - have we been handed a "document" rooted tree,
- # or a DOM-like tree that has "document" as its single child?
- if document.tagname == "document":
- self.write_html(document,stream)
- else:
- for element in document:
- self.write_html(element,stream)
-
- self.html.end("html")
- self.html.finish()
-
- def find_auto_footnotes(self,element):
- """Locate and number autonumbered footnotes...
- """
-
- if element.tagname == "#text":
- return
- elif element.tagname == "footnote":
- # This is a footnote body - it is the footnote bodies
- # that determine their order and numbering...
- name = auto = None
- if element.hasattr("name"):
- name = element["name"]
- if element.hasattr("auto"):
- auto = element["auto"]
- self.auto_footnote += 1
- element["auto-index"] = self.auto_footnote
- if auto:
- if name:
- if not self.auto_footnote_names.has_key(name):
- self.auto_footnote_names[name] = self.auto_footnote
- else:
- # Well, what should we do?
- # Removing it seems the best bet...
- del self.auto_footnote_names[name]
- else:
- self.auto_footnote_list.append(self.auto_footnote)
-
- for node in element:
- self.find_auto_footnotes(node)
-
- def write_document(self,element,stream):
- document_is_section = 0
- if element.hasattr("title"):
- title = self.html.escape(element["title"])
- else:
- firstchild = element[0]
- if firstchild.tagname == "title":
- title = self.html.escape(firstchild.astext())
- document_is_section = 1
- elif firstchild.hasattr("title"):
- title = self.html.escape(firstchild["title"])
- else:
- title = "Document produced by pysource"
-
- self.html.start("head")
- self.html.add("title",title)
- self.html.end("head")
-
- self.html.start("body")
- if document_is_section:
- # There is no internal <section> - instead we just
- # have a <document> whose first element is <title>
- # So, given that, pretend we ARE a section...
- self.write_section(element,stream)
- else:
- for node in element:
- self.write_html(node,stream)
-
- self.html.add("hr")
- self.html.start("p")
- self.html.add("em","Automatically generated by ",
- self.html.element("code","pysource"),
- " on %s\n"%time.ctime(time.time()))
- self.html.end("p")
- self.html.end("body")
-
- def write_text(self,element,stream):
- """Write out plain text.
- """
- self.html.add("text",self.html.escape(element.astext()))
-
- def write_html(self,element,stream):
- """Write out the HTML representation of `element` on `stream`.
- """
-
- name = element.tagname
- try:
- method = self.method_cache[name]
- except KeyError:
- method = getattr(self,"write_%s"%name,self.write_unknown)
- self.method_cache[name] = method
- method(element,stream)
-
- def write_unknown(self,element,stream):
- """Write out an element which we don't recognise.
- """
-
- self.html.add("p",self.html.element("comment","just a spacer"))
-
- self.html.start("font","&lt;%s"%element.tagname,color="red")
- for name,value in element.attlist():
- self.html.add("text"," %s='%s'"%(name,self.html.escape(value)))
- self.html.add("text","&gt;")
- self.html.end("font")
-
- for node in element:
- self.write_html(node,stream)
-
- self.html.add("font","&lt;/%s&gt;"%element.tagname,
- color="red")
-
- def write_section(self,element,stream):
- """Write a section - i.e., something with a title
- """
-
- self.level += 1
-
- if element.hasattr("name"):
- # Lazily, escape the name so we don't have to worry
- # about single quotes in it...
- name=self.html.escape(element["name"])
-
- # Hmm - we *want* to write "\n\n<a name='...'></a>"
- # which isn't *quite* what this does - maybe have a specialised
- # call in buildhtml.py?
- self.html.add("text",self.html.element("a",name=name))
- if self.visible_links:
- self.html.start("font",color="green")
- self.html.add("text","&lt;%s&gt;"%name)
- self.html.end("font")
-
- for node in element:
- self.write_html(node,stream)
-
- self.level -= 1
-
- def write_title(self,element,stream):
- if 1 <= self.level <= 6:
- self.html.start("h%d"%self.level)
- for node in element:
- self.write_html(node,stream)
- self.html.end("h%d"%self.level)
- else:
- # Put a warning here?
- self.html.start("p")
- self.html.start("font",size="-1",color="red")
- self.html.add("text","[problem: header level='%d']"%self.level)
- self.html.end("font")
- self.html.start("strong")
- for node in element:
- self.write_html(node,stream)
- self.html.end("strong")
- self.html.end("p")
-
- def write_transition(self,element,stream):
- self.html.start("p", # hmm - strictly not legal...
- self.html.element("hr"))
-
- def write_enumerated_list(self,element,stream):
- typedict = {"arabic" : "1",
- "roman" : "i",
- "Roman" : "I",
- "alpha" : "a",
- "Alpha" : "A"}
- try:
- enumtype = typedict[element["enumtype"]]
- except:
- enumtype = "1"
-
- # Does this match how DOCUTILS nodes work?
- if element.hasattr("start"):
- self.html.start("ol",type=enumtype,start=element["start"])
- else:
- self.html.start("ol",type=enumtype)
- for node in element:
- self.write_html(node,stream)
- self.html.end("ol")
-
- def write_bullet_list(self,element,stream):
- # Hmm - the translation is fairly arbitrary
- # - but at least consistent
- bulletdict = {"*" : "disc",
- "-" : "circle",
- "+" : "square"}
- try:
- bullet = bulletdict[element["bullet"]]
- except:
- bullet = None
-
- if bullet:
- self.html.start("ul",type=bullet)
- else:
- self.html.start("ul")
- for node in element:
- self.write_html(node,stream)
- self.html.end("ul")
-
- def write_definition_list(self,element,stream):
- self.html.start("dl")
- for node in element:
- self.write_html(node,stream)
- self.html.end("dl")
-
- def write_definition_list_item(self,element,stream):
- # Nothing special to do for this one
- for node in element:
- self.write_html(node,stream)
-
- def write_term(self,element,stream):
- self.html.start("dt")
- self.html.start("strong")
- for node in element:
- self.write_html(node,stream)
- self.html.add("text"," ") # to separate consecutive parts,
- # in option lists
- self.html.end("strong")
- self.html.end("dt")
-
- def write_list_item(self,element,stream):
- self.html.start("li")
- for node in element:
- self.write_html(node,stream)
- self.html.end("li")
-
- def write_option_list(self,element,stream):
- self.html.start("dl")
- for node in element:
- self.write_html(node,stream)
- self.html.end("dl")
-
- def write_option_list_item(self,element,stream):
- for node in element:
- self.write_html(node,stream)
-
- def write_option(self,element,stream):
- self.html.start("dt")
- self.html.start("strong")
- for node in element:
- self.write_html(node,stream)
- self.html.add("text"," ") # to separate consecutive parts,
- # in option lists
- self.html.end("strong")
- self.html.end("dt")
-
- def write_definition(self,element,stream):
- self.html.start("dd")
- for node in element:
- self.write_html(node,stream)
- self.html.end("dd")
-
- def write_short_option(self,element,stream):
- self.html.start("samp")
- for node in element:
- self.write_html(node,stream)
- self.html.end("samp")
-
- def write_long_option(self,element,stream):
- self.html.start("samp")
- for node in element:
- self.write_html(node,stream)
- self.html.end("samp")
-
- def write_vms_option(self,element,stream):
- self.html.start("samp")
- for node in element:
- self.write_html(node,stream)
- self.html.end("samp")
-
- def write_option_argument(self,element,stream):
- self.html.start("samp")
- for node in element:
- self.write_html(node,stream)
- self.html.end("samp")
-
- def write_description(self,element,stream):
- self.html.start("dd")
- for node in element:
- self.write_html(node,stream)
- self.html.end("dd")
-
- def write_field_list(self,element,stream):
- """Write out a fieldlist.
- """
- # The colour is for debugging purposes only!
- self.html.start("table",width="100%",bgcolor="palegreen")
-
- self.infield = 1
- for node in element:
- self.write_html(node,stream)
- self.infield = 0
-
- self.html.end("table")
-
- def write_field(self,element,stream):
- self.html.start("tr",valign="top",dps="field")
- for node in element:
- self.write_html(node,stream)
- self.html.end("tr")
-
- def write_field_name(self,element,stream):
- self.html.start("td",dps="field_name")
- self.html.start("strong")
- for node in element:
- self.write_html(node,stream)
- self.html.end("strong")
- self.html.end("td")
-
- def write_field_body(self,element,stream):
- self.infield = 1
- self.paranum = 0
- self.html.start("td",dps="field_body")
- for node in element:
- self.write_html(node,stream)
- self.html.end("td")
- self.infield = 0
-
- def write_biblio_field(self,element,stream,name):
- """Write out a document bibliographic datum.
- """
- self.infield = 1
- # The colour is for debugging purposes only!
- self.html.start("table",width="100%",bgcolor="palegreen")
- self.html.start("tr",valign="top")
- self.html.start("td",dps="biblio_field")
- self.html.add("strong",name)
-
- if len(element) != 1:
- raise HTMLError,"Found %d children in field %s"%\
- (len(element),name)
-
- self.write_field_body(element[0],stream)
-
- self.html.end("td","tr","table")
- self.infield = 0
-
- def write_subtitle(self,element,stream):
- self.write_biblio_field(element,stream,"Subtitle")
-
- def write_author(self,element,stream):
- self.write_biblio_field(element,stream,"Author")
-
- def write_authors(self,element,stream):
- self.write_biblio_field(element,stream,"Authors")
-
- def write_organization(self,element,stream):
- self.write_biblio_field(element,stream,"Organisation")
-
- def write_organisation(self,element,stream):
- self.write_biblio_field(element,stream,"Organisation")
-
- def write_contact(self,element,stream):
- self.write_biblio_field(element,stream,"Contact")
-
- def write_version(self,element,stream):
- self.write_biblio_field(element,stream,"Version")
-
- def write_status(self,element,stream):
- self.write_biblio_field(element,stream,"Status")
-
- def write_date(self,element,stream):
- self.write_biblio_field(element,stream,"Date")
-
- def write_revision(self,element,stream):
- self.write_biblio_field(element,stream,"Revision")
-
- def write_copyright(self,element,stream):
- self.write_biblio_field(element,stream,"Copyright")
-
- def write_abstract(self,element,stream):
- self.write_biblio_field(element,stream,"Abstract")
-
- def write_reference(self,element,stream):
- """Write a link - the "pointer" to a target.
-
- Doesn't yet handle "indirect" links...
- """
- if element.hasattr("refuri"):
- name = self.html.escape(element["refuri"])
- self.html.start("a",href=name)
- elif element.hasattr("refname"):
- # Escape the name to match what we do with titles...
- name = "#"+self.html.escape(element["refname"])
- self.html.start("a",href=name)
- else:
- self.write_unknown(element,stream)
- return
- for node in element:
- self.write_html(node,stream)
- self.html.end("a")
- if self.visible_links:
- self.html.start("font",color="green")
- self.html.add("text","&lt;%s&gt;"%name)
- self.html.end("font")
-
- def write_target(self,element,stream):
- """Write the target end of a link.
-
- Ultimately, the user should be able to choose to fold these into
- the document (i.e., into the "link" itself).
- """
- try:
- name = element["name"]
- except:
- name = "**no target name**"
-
- ##if not self.in_paragraph:
- ## self.html.start("p")
-
- # Provide some "debugging" information
- if self.visible_targets:
- self.html.start("font",color="green")
- self.html.start("strong")
- self.html.start("em")
- self.html.add("text",name)
- self.html.end("em")
- self.html.end("strong")
- self.html.end("font")
-
- self.html.add("a",name=self.html.escape(name))
-
- if element.has_key("refuri"):
- uri = self.html.escape(element["refuri"])
- self.html.add("text",":&nbsp;")
- self.html.add("a",element["refuri"],href=uri)
-
- ##if not self.in_paragraph:
- ## self.html.end("p")
-
- def write_footnote(self,element,stream):
- """Write out the body of a footnote.
-
- It's not entirely clear how to do this in HTML, so we'll
- just try for something distinctive...
- """
- name = auto = index = None
- if element.hasattr("name"):
- name = element["name"]
- if element.hasattr("auto"):
- auto = element["auto"]
- if element.hasattr("auto-index"):
- index = element["auto-index"]
-
- if auto and index == None:
- raise HTMLError,"Footnote auto-numbering has not been done"
-
- if name and auto:
- self.html.start("p")
- self.html.add("a",name=self.html.escape(name))
- self.html.add("text"," ")
- self.html.add("a",name=`index`)
- self.html.end("p")
- elif name:
- self.html.start("p")
- self.html.add("a",name=self.html.escape(name))
- self.html.end("p")
- elif auto:
- self.html.start("p")
- self.html.add("a",name=`index`)
- self.html.end("p")
- else:
- self.write_message(stream,level=2,
- text="Footnote doesn't have name"
- " or auto attributes")
-
- self.html.start("table",align="center",width="80%")
- self.html.start("tr")
- self.html.start("td")
-
- # Automatically numbered footnotes don't contain an explicit
- # <label> element, so we have to do it by hand...
- if auto:
- self.write_label(element,stream,index)
-
- for node in element:
- self.write_html(node,stream)
-
- self.html.end("td","tr","table")
-
- def write_label(self,element,stream,index=None):
- """Write out the label for a footnote.
- """
- self.html.add("p",
- self.html.element("hr"))
-
- self.html.start("p","Footnote ")
- if index == None:
- self.html.add("strong",element.astext())
- else:
- self.html.add("strong",`index`)
- self.html.end("p")
- self.html.add("br")
- self.html.add("hr")
-
- def write_footnote_reference(self,element,stream):
- """Write out the link to a footnote.
- """
- name = auto = None
- if element.hasattr("refname"):
- name = element["refname"]
- if element.hasattr("auto"):
- auto = element["auto"]
-
- if auto:
- if name:
- if self.auto_footnote_names.has_key(name):
- number = self.auto_footnote_names[name]
- else:
- self.write_message(stream,level=2,
- text="Autonumber footnote name"
- " '%s' doesn't match a"
- " footnote"%name)
- number = 0
- else:
- try:
- number = self.auto_footnote_list[self.auto_footnote_index]
- self.auto_footnote_index += 1
- except IndexError:
- # Hmm - probably a [#]_ with no footnotes for it to
- # point to - best we can do is write *something* out
- self.html.start("font",color=self.colours["Error"])
- self.html.add("text","[")
- self.html.add("strong","#")
- self.html.add("text","]")
- self.html.end("font")
- return
-
- if auto:
- self.html.start("a",href="#%d"%number)
- self.html.add("text","[")
- self.html.add("strong",`number`)
- self.html.add("text","]")
- self.html.end("a")
- elif name:
- self.html.start("a",href="#%s"%self.html.escape(name))
- self.html.add("text","[")
- self.html.add("strong",element.astext())
- self.html.add("text","]")
- self.html.end("a")
- else:
- self.write_unknown(element,stream)
- return
-
-
- def write_comment(self,element,stream):
- """Write out a comment
- """
- # Technically, this may not be enough, as we don't know what
- # they might *have* in the comment - but in practice, it's
- # likely to do...
- self.html.start("comment")
- for node in element:
- self.write_html(node,stream)
- self.html.end("comment")
-
- def write_paragraph(self,element,stream):
- """Write a new paragraph.
-
- This is a method simply because I do odd things inside
- a field body, to make it "look" better.
- """
- if self.html.last_tag() not in ["li","dd","td","th"]:
- self.html.start("p")
- write_slash_p = 1
- else:
- write_slash_p = 0
-
- for node in element:
- self.write_html(node,stream)
-
- if write_slash_p:
- self.html.end("p")
- return
-
-
- self.in_paragraph = 1
- if self.infield:
- self.write_field_paragraph(element,stream)
- else:
- self.html.start("p")
- for node in element:
- self.write_html(node,stream)
- self.html.end("p")
- self.in_paragraph = 0
-
- def write_field_paragraph(self,element,stream):
- """Write a new paragraph inside a field body.
- """
- started_row = 0
- if self.paranum > 0:
- self.html.start("tr")
- self.html.add("td") # an empty column...
- self.html.start("td",dps="paragraph")
- started_row = 1
- self.paranum += 1
- for node in element:
- self.write_html(node,stream)
- if self.paranum > 1:
- self.html.end("td")
- if started_row:
- self.html.end("tr")
-
- def write_table(self,element,stream):
- """Write out a table - initially in a very visible manner
- """
- self.html.start("table",border="1",align="center")
- for node in element:
- self.write_html(node,stream)
- self.html.end("table")
-
- def write_tgroup(self,element,stream):
- for node in element:
- self.write_html(node,stream)
-
- def write_colspec(self,element,stream):
- for node in element:
- self.write_html(node,stream)
-
- def write_rowspec(self,element,stream):
- for node in element:
- self.write_html(node,stream)
-
- def write_thead(self,element,stream):
- """Write out a table header section
- """
- self.html.start("thead")
- self.in_table_header = 1
- for node in element:
- self.write_html(node,stream)
- self.in_table_header = 0
- self.html.end("thead")
-
- def write_tbody(self,element,stream):
- """Write out a table body section
- """
- self.html.start("tbody")
- self.in_table_body = 1
- for node in element:
- self.write_html(node,stream)
- self.in_table_body = 0
- self.html.end("tbody")
-
- def write_row(self,element,stream):
- """Write out a table row.
- """
- if self.in_table_header:
- self.html.start("tr",valign="top",align="left")
- else:
- self.html.start("tr",valign="top")
- for node in element:
- self.write_html(node,stream)
- self.html.end("tr")
-
- def write_entry(self,element,stream):
- """Write out the equivalent of a table "entry" (e.g., HTML <td>)
- """
- keywords = {}
- if element.hasattr("morecols"):
- keywords["colspan"] = element["morecols"]+1
- if element.hasattr("morerows"):
- keywords["rowspan"] = element["morerows"]+1
- keywords["dps"] = "entry"
- self.html.start("td",**keywords)
-
- if self.in_table_header:
- self.html.start("strong")
-
- if len(element) == 0:
- # Since we're writing a table with a border, it looks better if
- # even an empty entry has *some* content - a non-breaking space
- # will suffice to make sure the entry is properly bordered
- self.html.add("text","&nbsp;")
- else:
- for node in element:
- self.write_html(node,stream)
-
- if self.in_table_header:
- self.html.end("strong")
-
- self.html.end("td")
-
- def write_message(self,stream,level=2,text=None,element=None):
- names = {1: "Information",
- 2: "Warning",
- 3: "Error",
- 4: "Fatal"}
-
- if level == 0 and not self.showinforms:
- return
- elif level == 1 and not self.showwarnings:
- return
-
- try:
- name = names[level]
- colour = self.colours[name]
- except:
- name = "Unrecognised warning level %d"%level
- colour = self.colours["Fatal"]
- bgcolour = self.colours["WarningBG"]
-
- self.html.start("table",width="100%%",bgcolor=bgcolour)
- self.html.start("tr")
- self.html.start("td")
- self.html.start("font",color=colour)
- self.html.add("strong",name)
- self.html.end("font")
- self.html.end("td","tr")
-
- self.html.start("tr")
- self.html.start("td")
- if text:
- self.html.add("text",text)
- if element:
- for node in element:
- self.write_html(node,stream)
- self.html.end("td","tr")
- self.html.end("table")
-
- def write_problematic(self,element,stream):
- self.html.start("a",href="#%s"%element["refid"])
- self.html.start("font",color="red")
- for node in element:
- self.write_html(node,stream)
- self.html.end("font")
- self.html.end("a")
-
- def write_system_message(self,element,stream):
- try:
- target = element["refid"]
- except:
- target = None
- if target:
- self.html.add("a","",name="%s"%target)
- self.write_message(stream,level=element["level"],element=element)
-
- def write_group(self,element,stream):
- """By default, we don't do anything with <group> tags.
- """
- for node in element:
- self.write_html(node,stream)
-
- def write_emphasis(self,element,stream):
- self.html.start("em")
- for node in element:
- self.write_html(node,stream)
- self.html.end("em")
-
- def write_strong(self,element,stream):
- self.html.start("strong")
- for node in element:
- self.write_html(node,stream)
- self.html.end("strong")
-
- def write_interpreted(self,element,stream):
- if element.hasattr("refname"):
- self.html.start("a",href="#"+self.html.escape(element["refname"]))
- inref = 1
- else:
- inref = 0
-
- self.html.start("samp",style="interpreted")
- if element.hasattr("role"):
- role = element["role"]
- if self.role_text.has_key(role):
- self.html.add("text","%s "%self.role_text[role])
-
- for node in element:
- self.write_html(node,stream)
- self.html.end("samp")
-
- if inref:
- self.html.end("a")
- if self.visible_links:
- self.html.start("font",color="green")
- self.html.add("text","&lt;%s&gt;"%element["refname"])
- self.html.end("font")
-
- def write_literal(self,element,stream):
- self.html.start("samp",style="literal")
- for node in element:
- self.write_html(node,stream)
- self.html.end("samp")
-
- def write_literal_block(self,element,stream):
- self.html.start("pre")
- for node in element:
- self.write_html(node,stream)
- self.html.end("pre")
-
- def write_doctest_block(self,element,stream):
- self.html.start("pre",style="doctest")
- for node in element:
- self.write_html(node,stream)
- self.html.end("pre")
-
- def write_block_quote(self,element,stream):
- self.html.start("blockquote")
- for node in element:
- self.write_html(node,stream)
- self.html.end("blockquote")
-
-
-# ----------------------------------------------------------------------
-class PythonWriter(Writer):
- """A Writer that understands how Python is represented using DOCUTILS.
-
- Note that as a princple, I don't believe that "modes" should add extra
- DOCUTILS nodes - in other words, any DOCUTILS tree should be presentable by
- the default writer (albeit maybe not very well).
- """
-
- python_colours = {"package" : "Aqua",
- "module" : "#FFFF00",
- "class" : "#99CCFF", # Python blue
- "method" : "#AAFFAA",
- "function" : "#FFAAFF",
- "docstring" : "#FFFFCC", # pale yellow-ish
- "generator" : "pink",
- }
-
- def write_group(self,element,stream):
- """Write out a group according to its style.
- """
-
- try:
- style = element["style"]
- except:
- style = None
-
- if style == "docstring":
- self.write_docstring(element,stream)
- elif style == "generator":
- self.html.start("table",bgcolor=self.python_colours["generator"],
- width="100%")
- self.html.start("tr")
- self.html.start("td")
-
- for node in element:
- self.write_html(node,stream)
-
- self.html.end("td")
- self.html.end("tr")
- self.html.end("table")
- else:
- for node in element:
- self.write_html(node,stream)
-
- def write_docstring(self,element,stream):
- """Write out a docstring
- """
-
- self.html.start("table",bgcolor=self.python_colours["docstring"],
- width="100%")
- self.html.start("tr")
- self.html.start("td")
-
- # Within a docstring, we want traditional HTML headers,
- # starting at <h2> and working downwards
- self.level = 1
-
- for node in element:
- self.write_html(node,stream)
-
- self.html.end("td")
- self.html.end("tr")
- self.html.end("table")
-
- def write_section(self,element,stream):
- """Write a section - i.e., something with a title
- """
-
- try:
- style = element["style"]
- except:
- style = None
-
- if style in ["package","module","class","method","function"]:
- self.write_py_section(element,stream,style)
- else:
- Writer.write_section(self,element,stream)
-
- def write_py_section(self,element,stream,style):
- """Write out the HTML for a Python section.
- """
-
- self.level += 1
-
- try:
- colour = self.python_colours[style]
- except:
- colour = self.colours["default"]
-
- self.html.start("table",width="100%",cellspacing="0")
-
- # First row - full width, coloured
- self.html.start("tr",bgcolor=colour)
- self.html.add("td",self.html.element("hr"),colspan="2")
- self.html.end("tr")
-
- # Now, if the section has a <title> and a <group> with
- # style="details", we want to treat them specially - and
- # we *know* that they should, if present, be the first
- # two child elements...
- # Optional first-and-a-halfth row
- offset = self.write_py_section_details(element,stream,colour)
-
- if len(element.children) > offset:
- # Second row - left hand margin coloured, "body" not
- self.html.start("tr")
- self.html.add("td","&nbsp;",width="1%",bgcolor=colour)
- self.html.start("td",width="99%")
-
- # More detail needed here?
- for node in element.children[offset:]:
- self.write_html(node,stream)
-
- self.html.end("td")
- self.html.end("tr")
-
- # Third row - full width coloured
- self.html.start("tr",bgcolor=colour)
- self.html.add("td",self.html.element("hr"),colspan="2")
- self.html.end("tr")
-
- if self.got_contents:
- # Fourth row - full width coloured
- self.html.start("tr",bgcolor=colour)
- self.html.add("td","&nbsp;")
- self.html.start("td",align="right")
- self.html.add("text","Return to ")
- self.html.add("a","Contents",href="#contents")
- self.html.end("td")
- self.html.end("tr")
-
- self.html.end("table")
-
- self.level -= 1
-
- def write_py_section_details(self,element,stream,colour):
- """Deal with the title and details for a Python section.
-
- Returns the offset within the <section> elements children
- at which we should continue processing...
- """
- offset = 0
- if element[0].tagname == "title":
- offset = 1
- self.html.start("tr",bgcolor=colour)
- self.html.start("td",colspan="2")
- self.html.start("table",width="100%")
- self.html.start("tr",valign="top")
- self.html.start("td")
- # Hmm. It doesn't work too well using <h2>..<h6> as header
- # elements for nested module, class, etc. Let's do this
- # by "hand"
- self.html.start("font",size="+2")
- for node in element[0]:
- self.write_html(node,stream)
- self.html.end("font")
- self.html.end("td")
- self.html.end("tr")
-
- if element[1].tagname == "group" and \
- element[1].hasattr("style") and \
- element[1]["style"] == "details":
- offset = 2
- self.html.start("tr")
- self.html.start("td",align="right")
- self.write_html(element[1],stream)
- self.html.end("td")
- self.html.end("tr")
- self.html.end("table")
- self.html.end("td")
- self.html.end("tr")
- return offset
diff --git a/sandbox/tibs/pysource/notes/notes.py b/sandbox/tibs/pysource/notes/notes.py
deleted file mode 100755
index a7fd81f51..000000000
--- a/sandbox/tibs/pysource/notes/notes.py
+++ /dev/null
@@ -1,115 +0,0 @@
-"""Notes (i.e., me working things out...)
-
-Given the following Python::
-
- def func(a,b=1,c='jim',d=None,e=[],f={'a':1},g=(1,2,3)):
-
-the tree produced by compiler looks like::
-
- <Function> 'func' 'a' 'b' 'c' 'd' 'e' 'f' 'g'
- <Const> 1
- <Const> 'jim'
- <Name> 'None'
- <List>
- <Dict>
- <Const> 'a'
- <Const> 1
- <Tuple>
- <Const> 1
- <Const> 2
- <Const> 3 0
-
-If one has::
-
- def func2(a,*args,**kargs):
-
-one gets::
-
- <Function> 'func2' 'a' 'args' 'kargs' 3 None
-
-and lastly::
-
- def func3((a,b,c),d):
-
-gives::
-
- <Function> 'func3' 'a' 'b' 'c' 'd' 0 None
-
-
-`compiler.misc` defines `flatten(tup)` - maybe I should try it?
-
-"""
-
-
-# compiler.transformer contains this useful set of comments:
-#
-#
-# The output tree has the following nodes:
-#
-# Source Python line #'s appear at the end of each of all of these nodes
-# If a line # doesn't apply, there will be a None instead.
-#
-# module: doc, node
-# stmt: [ node1, ..., nodeN ]
-# function: name, argnames, defaults, flags, doc, codeNode
-# lambda: argnames, defaults, flags, codeNode
-# classdef: name, bases, doc, codeNode
-# pass:
-# break:
-# continue:
-# for: assignNode, listNode, bodyNode, elseNode
-# while: testNode, bodyNode, elseNode
-# if: [ (testNode, suiteNode), ... ], elseNode
-# exec: expr1Node, expr2Node, expr3Node
-# from: modname, [ name1, ..., nameN ]
-# import: [ name1, ..., nameN ]
-# raise: expr1Node, expr2Node, expr3Node
-# tryfinally: trySuiteNode, finSuiteNode
-# tryexcept: trySuiteNode, [ (exprNode, assgnNode, suiteNode), ... ], elseNode
-# return: valueNode
-# const: value
-# print: [ node1, ..., nodeN ] [, dest]
-# printnl: [ node1, ..., nodeN ] [, dest]
-# discard: exprNode
-# augassign: node, op, expr
-# assign: [ node1, ..., nodeN ], exprNode
-# ass_tuple: [ node1, ..., nodeN ]
-# ass_list: [ node1, ..., nodeN ]
-# ass_name: name, flags
-# ass_attr: exprNode, attrname, flags
-# list: [ node1, ..., nodeN ]
-# dict: [ (key1, val1), ..., (keyN, valN) ]
-# not: exprNode
-# compare: exprNode, [ (op, node), ..., (op, node) ]
-# name: name
-# global: [ name1, ..., nameN ]
-# backquote: node
-# getattr: exprNode, attrname
-# call_func: node, [ arg1, ..., argN ]
-# keyword: name, exprNode
-# subscript: exprNode, flags, [ sub1, ..., subN ]
-# ellipsis:
-# sliceobj: [ node1, ..., nodeN ]
-# slice: exprNode, flags, lowerNode, upperNode
-# assert: expr1, expr2
-#
-# Compiled as "binary" ops:
-# tuple: [ node1, ..., nodeN ]
-# or: [ node1, ..., nodeN ]
-# and: [ node1, ..., nodeN ]
-# bitor: [ node1, ..., nodeN ]
-# bitxor: [ node1, ..., nodeN ]
-# bitand: [ node1, ..., nodeN ]
-#
-# Operations easily evaluateable on constants:
-# <<: exprNode, shiftNode
-# >>: exprNode, shiftNode
-# +: leftNode, rightNode
-# -: leftNode, rightNode
-# *: leftNode, rightNode
-# /: leftNode, rightNode
-# %: leftNode, rightNode
-# power: leftNode, rightNode
-# unary+: node
-# unary-: node
-# invert: node
diff --git a/sandbox/tibs/pysource/notes/notes.txt b/sandbox/tibs/pysource/notes/notes.txt
deleted file mode 100644
index 548d792a1..000000000
--- a/sandbox/tibs/pysource/notes/notes.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-Paul Moore's summary of backquoted markup possibilities::
-
- `xxxxx`_ - named hyperlink reference (type 2)
- `xxxxx`__ - anonymous hyperlink reference (type 2)
- _`xxxx` - inline hyperlink targets
- `/xxx/` - substitution reference
- `xxxxx` - interpreted text
diff --git a/sandbox/tibs/pysource/notes/roles.txt b/sandbox/tibs/pysource/notes/roles.txt
deleted file mode 100644
index b063e026d..000000000
--- a/sandbox/tibs/pysource/notes/roles.txt
+++ /dev/null
@@ -1,61 +0,0 @@
-The following is taken from the DPS document pysource-reader.txt::
-
- Interpreted Text
- ================
-
- DTD elements: package, module, class, method, function,
- module_attribute, class_attribute, instance_attribute, variable,
- parameter, type, exception_class, warning_class.
-
- In Python docstrings, interpreted text is used to classify and mark up
- program identifiers, such as the names of variables, functions,
- classes, and modules. If the identifier alone is given, its role is
- inferred implicitly according to the Python namespace lookup rules.
- For functions and methods (even when dynamically assigned),
- parentheses ('()') may be included::
-
- This function uses `another()` to do its work.
-
- For class, instance and module attributes, dotted identifiers are used
- when necessary::
-
- class Keeper(Storer):
-
- """
- Extend `Storer`. Class attribute `instances` keeps track of
- the number of `Keeper` objects instantiated.
- """
-
- instances = 0
- """How many `Keeper` objects are there?"""
-
- def __init__(self):
- """
- Extend `Storer.__init__()` to keep track of instances.
-
- Keep count in `self.instances` and data in `self.data`.
- """
- Storer.__init__(self)
- self.instances += 1
-
- self.data = []
- """Store data in a list, most recent last."""
-
- def storedata(self, data):
- """
- Extend `Storer.storedata()`; append new `data` to a list
- (in `self.data`).
- """
- self.data = data
-
- To classify identifiers explicitly, the role is given along with the
- identifier in either prefix or suffix form::
-
- Use :method:`Keeper.storedata` to store the object's data in
- `Keeper.data`:instance_attribute:.
-
- The role may be one of 'package', 'module', 'class', 'method',
- 'function', 'module_attribute', 'class_attribute',
- 'instance_attribute', 'variable', 'parameter', 'type',
- 'exception_class', 'exception', 'warning_class', or 'warning'. Other
- roles may be defined.
diff --git a/sandbox/tibs/pysource/notes/scope.txt b/sandbox/tibs/pysource/notes/scope.txt
deleted file mode 100644
index 1ad889c1b..000000000
--- a/sandbox/tibs/pysource/notes/scope.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-On finding names
-================
-
-We are not trying for a general solution to the problem of "find the item
-that is being referred to" - we are just trying to provide useful links
-between <interpreted> items in docstrings and those things that they
-might reasonably be expected to be referring to.
-
-Some rules thus occur.
-
-1. We will not show attributes, docstring or not, if they are not
-
- a. At module level (so a ModuleValue)
- b. Within a class (so a ClassValue)
- c. Within a method called __init__ or __new__.
-
- So discard any attributes that do not match these criteria.
-
-Hmm - is that the only rule? Can it be so simple?
diff --git a/sandbox/tibs/pysource/notes/string.html b/sandbox/tibs/pysource/notes/string.html
deleted file mode 100755
index e09c30e2b..000000000
--- a/sandbox/tibs/pysource/notes/string.html
+++ /dev/null
@@ -1,225 +0,0 @@
-
-<!doctype html public "-//W3C//DTD HTML 4.0 Transitional//EN">
-<html><head><title>Python: module string</title>
-<style type="text/css"><!--
-TT { font-family: lucidatypewriter, lucida console, courier }
---></style></head><body bgcolor="#f0f0f8">
-
-<table width="100%" cellspacing=0 cellpadding=2 border=0>
-<tr bgcolor="#7799ee">
-<td valign=bottom><small>&nbsp;<br></small
-><font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong>string</strong></big></big></font></td
-><td align=right valign=bottom
-><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:///C|/python21/lib/string.py">c:\python21\lib\string.py</a></font></td></tr></table>
- <p><small><tt>A&nbsp;collection&nbsp;of&nbsp;string&nbsp;operations&nbsp;(most&nbsp;are&nbsp;no&nbsp;longer&nbsp;used&nbsp;in&nbsp;Python&nbsp;1.6).<br>
-&nbsp;<br>
-Warning:&nbsp;most&nbsp;of&nbsp;the&nbsp;code&nbsp;you&nbsp;see&nbsp;here&nbsp;isn't&nbsp;normally&nbsp;used&nbsp;nowadays.&nbsp;&nbsp;With<br>
-Python&nbsp;1.6,&nbsp;many&nbsp;of&nbsp;these&nbsp;functions&nbsp;are&nbsp;implemented&nbsp;as&nbsp;methods&nbsp;on&nbsp;the<br>
-standard&nbsp;string&nbsp;object.&nbsp;They&nbsp;used&nbsp;to&nbsp;be&nbsp;implemented&nbsp;by&nbsp;a&nbsp;built-in&nbsp;module<br>
-called&nbsp;strop,&nbsp;but&nbsp;strop&nbsp;is&nbsp;now&nbsp;obsolete&nbsp;itself.<br>
-&nbsp;<br>
-Public&nbsp;module&nbsp;variables:<br>
-&nbsp;<br>
-whitespace&nbsp;--&nbsp;a&nbsp;string&nbsp;containing&nbsp;all&nbsp;characters&nbsp;considered&nbsp;whitespace<br>
-lowercase&nbsp;--&nbsp;a&nbsp;string&nbsp;containing&nbsp;all&nbsp;characters&nbsp;considered&nbsp;lowercase&nbsp;letters<br>
-uppercase&nbsp;--&nbsp;a&nbsp;string&nbsp;containing&nbsp;all&nbsp;characters&nbsp;considered&nbsp;uppercase&nbsp;letters<br>
-letters&nbsp;--&nbsp;a&nbsp;string&nbsp;containing&nbsp;all&nbsp;characters&nbsp;considered&nbsp;letters<br>
-digits&nbsp;--&nbsp;a&nbsp;string&nbsp;containing&nbsp;all&nbsp;characters&nbsp;considered&nbsp;decimal&nbsp;digits<br>
-hexdigits&nbsp;--&nbsp;a&nbsp;string&nbsp;containing&nbsp;all&nbsp;characters&nbsp;considered&nbsp;hexadecimal&nbsp;digits<br>
-octdigits&nbsp;--&nbsp;a&nbsp;string&nbsp;containing&nbsp;all&nbsp;characters&nbsp;considered&nbsp;octal&nbsp;digits<br>
-punctuation&nbsp;--&nbsp;a&nbsp;string&nbsp;containing&nbsp;all&nbsp;characters&nbsp;considered&nbsp;punctuation<br>
-printable&nbsp;--&nbsp;a&nbsp;string&nbsp;containing&nbsp;all&nbsp;characters&nbsp;considered&nbsp;printable</tt></small></p>
-
-<p><table width="100%" cellspacing=0 cellpadding=2 border=0>
-<tr bgcolor="#eeaa77">
-<td colspan=3 valign=bottom><small><small>&nbsp;<br></small></small
-><font color="#ffffff" face="helvetica, arial"><big><strong>Functions</strong></big></font></td></tr>
-
-<tr><td bgcolor="#eeaa77"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;&nbsp;</td>
-<td width="100%"><dl><dt><a name="-_float"><strong>_float</strong></a> = float(...)<dd><small><tt>float(x)&nbsp;-&gt;&nbsp;floating&nbsp;point&nbsp;number<br>
-&nbsp;<br>
-Convert&nbsp;a&nbsp;string&nbsp;or&nbsp;number&nbsp;to&nbsp;a&nbsp;floating&nbsp;point&nbsp;number,&nbsp;if&nbsp;possible.</tt></small></dl>
- <dl><dt><a name="-_int"><strong>_int</strong></a> = int(...)<dd><small><tt>int(x[,&nbsp;base])&nbsp;-&gt;&nbsp;integer<br>
-&nbsp;<br>
-Convert&nbsp;a&nbsp;string&nbsp;or&nbsp;number&nbsp;to&nbsp;an&nbsp;integer,&nbsp;if&nbsp;possible.&nbsp;&nbsp;A&nbsp;floating&nbsp;point<br>
-argument&nbsp;will&nbsp;be&nbsp;truncated&nbsp;towards&nbsp;zero&nbsp;(this&nbsp;does&nbsp;not&nbsp;include&nbsp;a&nbsp;string<br>
-representation&nbsp;of&nbsp;a&nbsp;floating&nbsp;point&nbsp;number!)&nbsp;&nbsp;When&nbsp;converting&nbsp;a&nbsp;string,&nbsp;use<br>
-the&nbsp;optional&nbsp;base.&nbsp;&nbsp;It&nbsp;is&nbsp;an&nbsp;error&nbsp;to&nbsp;supply&nbsp;a&nbsp;base&nbsp;when&nbsp;converting&nbsp;a<br>
-non-string.</tt></small></dl>
- <dl><dt><a name="-_long"><strong>_long</strong></a> = long(...)<dd><small><tt>long(x)&nbsp;-&gt;&nbsp;long&nbsp;integer<br>
-long(x,&nbsp;base)&nbsp;-&gt;&nbsp;long&nbsp;integer<br>
-&nbsp;<br>
-Convert&nbsp;a&nbsp;string&nbsp;or&nbsp;number&nbsp;to&nbsp;a&nbsp;long&nbsp;integer,&nbsp;if&nbsp;possible.&nbsp;&nbsp;A&nbsp;floating<br>
-point&nbsp;argument&nbsp;will&nbsp;be&nbsp;truncated&nbsp;towards&nbsp;zero&nbsp;(this&nbsp;does&nbsp;not&nbsp;include&nbsp;a<br>
-string&nbsp;representation&nbsp;of&nbsp;a&nbsp;floating&nbsp;point&nbsp;number!)&nbsp;&nbsp;When&nbsp;converting&nbsp;a<br>
-string,&nbsp;use&nbsp;the&nbsp;given&nbsp;base.&nbsp;&nbsp;It&nbsp;is&nbsp;an&nbsp;error&nbsp;to&nbsp;supply&nbsp;a&nbsp;base&nbsp;when<br>
-converting&nbsp;a&nbsp;non-string.</tt></small></dl>
- <dl><dt><a name="-atof"><strong>atof</strong></a>(s)<dd><small><tt><a href="#-atof">atof</a>(s)&nbsp;-&gt;&nbsp;float<br>
-&nbsp;<br>
-Return&nbsp;the&nbsp;floating&nbsp;point&nbsp;number&nbsp;represented&nbsp;by&nbsp;the&nbsp;string&nbsp;s.</tt></small></dl>
- <dl><dt><a name="-atoi"><strong>atoi</strong></a>(s, base<small><font color="#909090">=10</font></small>)<dd><small><tt><a href="#-atoi">atoi</a>(s&nbsp;[,base])&nbsp;-&gt;&nbsp;int<br>
-&nbsp;<br>
-Return&nbsp;the&nbsp;integer&nbsp;represented&nbsp;by&nbsp;the&nbsp;string&nbsp;s&nbsp;in&nbsp;the&nbsp;given<br>
-base,&nbsp;which&nbsp;defaults&nbsp;to&nbsp;10.&nbsp;&nbsp;The&nbsp;string&nbsp;s&nbsp;must&nbsp;consist&nbsp;of&nbsp;one<br>
-or&nbsp;more&nbsp;digits,&nbsp;possibly&nbsp;preceded&nbsp;by&nbsp;a&nbsp;sign.&nbsp;&nbsp;If&nbsp;base&nbsp;is&nbsp;0,&nbsp;it<br>
-is&nbsp;chosen&nbsp;from&nbsp;the&nbsp;leading&nbsp;characters&nbsp;of&nbsp;s,&nbsp;0&nbsp;for&nbsp;octal,&nbsp;0x&nbsp;or<br>
-0X&nbsp;for&nbsp;hexadecimal.&nbsp;&nbsp;If&nbsp;base&nbsp;is&nbsp;16,&nbsp;a&nbsp;preceding&nbsp;0x&nbsp;or&nbsp;0X&nbsp;is<br>
-accepted.</tt></small></dl>
- <dl><dt><a name="-atol"><strong>atol</strong></a>(s, base<small><font color="#909090">=10</font></small>)<dd><small><tt><a href="#-atol">atol</a>(s&nbsp;[,base])&nbsp;-&gt;&nbsp;long<br>
-&nbsp;<br>
-Return&nbsp;the&nbsp;long&nbsp;integer&nbsp;represented&nbsp;by&nbsp;the&nbsp;string&nbsp;s&nbsp;in&nbsp;the<br>
-given&nbsp;base,&nbsp;which&nbsp;defaults&nbsp;to&nbsp;10.&nbsp;&nbsp;The&nbsp;string&nbsp;s&nbsp;must&nbsp;consist<br>
-of&nbsp;one&nbsp;or&nbsp;more&nbsp;digits,&nbsp;possibly&nbsp;preceded&nbsp;by&nbsp;a&nbsp;sign.&nbsp;&nbsp;If&nbsp;base<br>
-is&nbsp;0,&nbsp;it&nbsp;is&nbsp;chosen&nbsp;from&nbsp;the&nbsp;leading&nbsp;characters&nbsp;of&nbsp;s,&nbsp;0&nbsp;for<br>
-octal,&nbsp;0x&nbsp;or&nbsp;0X&nbsp;for&nbsp;hexadecimal.&nbsp;&nbsp;If&nbsp;base&nbsp;is&nbsp;16,&nbsp;a&nbsp;preceding<br>
-0x&nbsp;or&nbsp;0X&nbsp;is&nbsp;accepted.&nbsp;&nbsp;A&nbsp;trailing&nbsp;L&nbsp;or&nbsp;l&nbsp;is&nbsp;not&nbsp;accepted,<br>
-unless&nbsp;base&nbsp;is&nbsp;0.</tt></small></dl>
- <dl><dt><a name="-capitalize"><strong>capitalize</strong></a>(s)<dd><small><tt><a href="#-capitalize">capitalize</a>(s)&nbsp;-&gt;&nbsp;string<br>
-&nbsp;<br>
-Return&nbsp;a&nbsp;copy&nbsp;of&nbsp;the&nbsp;string&nbsp;s&nbsp;with&nbsp;only&nbsp;its&nbsp;first&nbsp;character<br>
-capitalized.</tt></small></dl>
- <dl><dt><a name="-capwords"><strong>capwords</strong></a>(s, sep<small><font color="#909090">=None</font></small>)<dd><small><tt><a href="#-capwords">capwords</a>(s,&nbsp;[sep])&nbsp;-&gt;&nbsp;string<br>
-&nbsp;<br>
-Split&nbsp;the&nbsp;argument&nbsp;into&nbsp;words&nbsp;using&nbsp;split,&nbsp;capitalize&nbsp;each<br>
-word&nbsp;using&nbsp;capitalize,&nbsp;and&nbsp;join&nbsp;the&nbsp;capitalized&nbsp;words&nbsp;using<br>
-join.&nbsp;Note&nbsp;that&nbsp;this&nbsp;replaces&nbsp;runs&nbsp;of&nbsp;whitespace&nbsp;characters&nbsp;by<br>
-a&nbsp;single&nbsp;space.</tt></small></dl>
- <dl><dt><a name="-center"><strong>center</strong></a>(s, width)<dd><small><tt><a href="#-center">center</a>(s,&nbsp;width)&nbsp;-&gt;&nbsp;string<br>
-&nbsp;<br>
-Return&nbsp;a&nbsp;center&nbsp;version&nbsp;of&nbsp;s,&nbsp;in&nbsp;a&nbsp;field&nbsp;of&nbsp;the&nbsp;specified<br>
-width.&nbsp;padded&nbsp;with&nbsp;spaces&nbsp;as&nbsp;needed.&nbsp;&nbsp;The&nbsp;string&nbsp;is&nbsp;never<br>
-truncated.</tt></small></dl>
- <dl><dt><a name="-count"><strong>count</strong></a>(s, *args)<dd><small><tt><a href="#-count">count</a>(s,&nbsp;sub[,&nbsp;start[,end]])&nbsp;-&gt;&nbsp;int<br>
-&nbsp;<br>
-Return&nbsp;the&nbsp;number&nbsp;of&nbsp;occurrences&nbsp;of&nbsp;substring&nbsp;sub&nbsp;in&nbsp;string<br>
-s[start:end].&nbsp;&nbsp;Optional&nbsp;arguments&nbsp;start&nbsp;and&nbsp;end&nbsp;are<br>
-interpreted&nbsp;as&nbsp;in&nbsp;slice&nbsp;notation.</tt></small></dl>
- <dl><dt><a name="-expandtabs"><strong>expandtabs</strong></a>(s, tabsize<small><font color="#909090">=8</font></small>)<dd><small><tt><a href="#-expandtabs">expandtabs</a>(s&nbsp;[,tabsize])&nbsp;-&gt;&nbsp;string<br>
-&nbsp;<br>
-Return&nbsp;a&nbsp;copy&nbsp;of&nbsp;the&nbsp;string&nbsp;s&nbsp;with&nbsp;all&nbsp;tab&nbsp;characters&nbsp;replaced<br>
-by&nbsp;the&nbsp;appropriate&nbsp;number&nbsp;of&nbsp;spaces,&nbsp;depending&nbsp;on&nbsp;the&nbsp;current<br>
-column,&nbsp;and&nbsp;the&nbsp;tabsize&nbsp;(default&nbsp;8).</tt></small></dl>
- <dl><dt><a name="-find"><strong>find</strong></a>(s, *args)<dd><small><tt><a href="#-find">find</a>(s,&nbsp;sub&nbsp;[,start&nbsp;[,end]])&nbsp;-&gt;&nbsp;in<br>
-&nbsp;<br>
-Return&nbsp;the&nbsp;lowest&nbsp;index&nbsp;in&nbsp;s&nbsp;where&nbsp;substring&nbsp;sub&nbsp;is&nbsp;found,<br>
-such&nbsp;that&nbsp;sub&nbsp;is&nbsp;contained&nbsp;within&nbsp;s[start,end].&nbsp;&nbsp;Optional<br>
-arguments&nbsp;start&nbsp;and&nbsp;end&nbsp;are&nbsp;interpreted&nbsp;as&nbsp;in&nbsp;slice&nbsp;notation.<br>
-&nbsp;<br>
-Return&nbsp;-1&nbsp;on&nbsp;failure.</tt></small></dl>
- <dl><dt><a name="-index"><strong>index</strong></a>(s, *args)<dd><small><tt><a href="#-index">index</a>(s,&nbsp;sub&nbsp;[,start&nbsp;[,end]])&nbsp;-&gt;&nbsp;int<br>
-&nbsp;<br>
-Like&nbsp;find&nbsp;but&nbsp;raises&nbsp;ValueError&nbsp;when&nbsp;the&nbsp;substring&nbsp;is&nbsp;not&nbsp;found.</tt></small></dl>
- <dl><dt><a name="-join"><strong>join</strong></a>(words, sep<small><font color="#909090">=' '</font></small>)<dd><small><tt><a href="#-join">join</a>(list&nbsp;[,sep])&nbsp;-&gt;&nbsp;string<br>
-&nbsp;<br>
-Return&nbsp;a&nbsp;string&nbsp;composed&nbsp;of&nbsp;the&nbsp;words&nbsp;in&nbsp;list,&nbsp;with<br>
-intervening&nbsp;occurrences&nbsp;of&nbsp;sep.&nbsp;&nbsp;The&nbsp;default&nbsp;separator&nbsp;is&nbsp;a<br>
-single&nbsp;space.<br>
-&nbsp;<br>
-(joinfields&nbsp;and&nbsp;join&nbsp;are&nbsp;synonymous)</tt></small></dl>
- <dl><dt><a name="-joinfields"><strong>joinfields</strong></a> = join(words, sep<small><font color="#909090">=' '</font></small>)<dd><small><tt><a href="#-join">join</a>(list&nbsp;[,sep])&nbsp;-&gt;&nbsp;string<br>
-&nbsp;<br>
-Return&nbsp;a&nbsp;string&nbsp;composed&nbsp;of&nbsp;the&nbsp;words&nbsp;in&nbsp;list,&nbsp;with<br>
-intervening&nbsp;occurrences&nbsp;of&nbsp;sep.&nbsp;&nbsp;The&nbsp;default&nbsp;separator&nbsp;is&nbsp;a<br>
-single&nbsp;space.<br>
-&nbsp;<br>
-(joinfields&nbsp;and&nbsp;join&nbsp;are&nbsp;synonymous)</tt></small></dl>
- <dl><dt><a name="-ljust"><strong>ljust</strong></a>(s, width)<dd><small><tt><a href="#-ljust">ljust</a>(s,&nbsp;width)&nbsp;-&gt;&nbsp;string<br>
-&nbsp;<br>
-Return&nbsp;a&nbsp;left-justified&nbsp;version&nbsp;of&nbsp;s,&nbsp;in&nbsp;a&nbsp;field&nbsp;of&nbsp;the<br>
-specified&nbsp;width,&nbsp;padded&nbsp;with&nbsp;spaces&nbsp;as&nbsp;needed.&nbsp;&nbsp;The&nbsp;string&nbsp;is<br>
-never&nbsp;truncated.</tt></small></dl>
- <dl><dt><a name="-lower"><strong>lower</strong></a>(s)<dd><small><tt><a href="#-lower">lower</a>(s)&nbsp;-&gt;&nbsp;string<br>
-&nbsp;<br>
-Return&nbsp;a&nbsp;copy&nbsp;of&nbsp;the&nbsp;string&nbsp;s&nbsp;converted&nbsp;to&nbsp;lowercase.</tt></small></dl>
- <dl><dt><a name="-lstrip"><strong>lstrip</strong></a>(s)<dd><small><tt><a href="#-lstrip">lstrip</a>(s)&nbsp;-&gt;&nbsp;string<br>
-&nbsp;<br>
-Return&nbsp;a&nbsp;copy&nbsp;of&nbsp;the&nbsp;string&nbsp;s&nbsp;with&nbsp;leading&nbsp;whitespace&nbsp;removed.</tt></small></dl>
- <dl><dt><a name="-maketrans"><strong>maketrans</strong></a>(...)<dd><small><tt><a href="#-maketrans">maketrans</a>(frm,&nbsp;to)&nbsp;-&gt;&nbsp;string<br>
-&nbsp;<br>
-Return&nbsp;a&nbsp;translation&nbsp;table&nbsp;(a&nbsp;string&nbsp;of&nbsp;256&nbsp;bytes&nbsp;long)<br>
-suitable&nbsp;for&nbsp;use&nbsp;in&nbsp;string.translate.&nbsp;&nbsp;The&nbsp;strings&nbsp;frm&nbsp;and&nbsp;to<br>
-must&nbsp;be&nbsp;of&nbsp;the&nbsp;same&nbsp;length.</tt></small></dl>
- <dl><dt><a name="-replace"><strong>replace</strong></a>(s, old, new, maxsplit<small><font color="#909090">=-1</font></small>)<dd><small><tt>replace&nbsp;(str,&nbsp;old,&nbsp;new[,&nbsp;maxsplit])&nbsp;-&gt;&nbsp;string<br>
-&nbsp;<br>
-Return&nbsp;a&nbsp;copy&nbsp;of&nbsp;string&nbsp;str&nbsp;with&nbsp;all&nbsp;occurrences&nbsp;of&nbsp;substring<br>
-old&nbsp;replaced&nbsp;by&nbsp;new.&nbsp;If&nbsp;the&nbsp;optional&nbsp;argument&nbsp;maxsplit&nbsp;is<br>
-given,&nbsp;only&nbsp;the&nbsp;first&nbsp;maxsplit&nbsp;occurrences&nbsp;are&nbsp;replaced.</tt></small></dl>
- <dl><dt><a name="-rfind"><strong>rfind</strong></a>(s, *args)<dd><small><tt><a href="#-rfind">rfind</a>(s,&nbsp;sub&nbsp;[,start&nbsp;[,end]])&nbsp;-&gt;&nbsp;int<br>
-&nbsp;<br>
-Return&nbsp;the&nbsp;highest&nbsp;index&nbsp;in&nbsp;s&nbsp;where&nbsp;substring&nbsp;sub&nbsp;is&nbsp;found,<br>
-such&nbsp;that&nbsp;sub&nbsp;is&nbsp;contained&nbsp;within&nbsp;s[start,end].&nbsp;&nbsp;Optional<br>
-arguments&nbsp;start&nbsp;and&nbsp;end&nbsp;are&nbsp;interpreted&nbsp;as&nbsp;in&nbsp;slice&nbsp;notation.<br>
-&nbsp;<br>
-Return&nbsp;-1&nbsp;on&nbsp;failure.</tt></small></dl>
- <dl><dt><a name="-rindex"><strong>rindex</strong></a>(s, *args)<dd><small><tt><a href="#-rindex">rindex</a>(s,&nbsp;sub&nbsp;[,start&nbsp;[,end]])&nbsp;-&gt;&nbsp;int<br>
-&nbsp;<br>
-Like&nbsp;rfind&nbsp;but&nbsp;raises&nbsp;ValueError&nbsp;when&nbsp;the&nbsp;substring&nbsp;is&nbsp;not&nbsp;found.</tt></small></dl>
- <dl><dt><a name="-rjust"><strong>rjust</strong></a>(s, width)<dd><small><tt><a href="#-rjust">rjust</a>(s,&nbsp;width)&nbsp;-&gt;&nbsp;string<br>
-&nbsp;<br>
-Return&nbsp;a&nbsp;right-justified&nbsp;version&nbsp;of&nbsp;s,&nbsp;in&nbsp;a&nbsp;field&nbsp;of&nbsp;the<br>
-specified&nbsp;width,&nbsp;padded&nbsp;with&nbsp;spaces&nbsp;as&nbsp;needed.&nbsp;&nbsp;The&nbsp;string&nbsp;is<br>
-never&nbsp;truncated.</tt></small></dl>
- <dl><dt><a name="-rstrip"><strong>rstrip</strong></a>(s)<dd><small><tt><a href="#-rstrip">rstrip</a>(s)&nbsp;-&gt;&nbsp;string<br>
-&nbsp;<br>
-Return&nbsp;a&nbsp;copy&nbsp;of&nbsp;the&nbsp;string&nbsp;s&nbsp;with&nbsp;trailing&nbsp;whitespace<br>
-removed.</tt></small></dl>
- <dl><dt><a name="-split"><strong>split</strong></a>(s, sep<small><font color="#909090">=None</font></small>, maxsplit<small><font color="#909090">=-1</font></small>)<dd><small><tt><a href="#-split">split</a>(s&nbsp;[,sep&nbsp;[,maxsplit]])&nbsp;-&gt;&nbsp;list&nbsp;of&nbsp;strings<br>
-&nbsp;<br>
-Return&nbsp;a&nbsp;list&nbsp;of&nbsp;the&nbsp;words&nbsp;in&nbsp;the&nbsp;string&nbsp;s,&nbsp;using&nbsp;sep&nbsp;as&nbsp;the<br>
-delimiter&nbsp;string.&nbsp;&nbsp;If&nbsp;maxsplit&nbsp;is&nbsp;given,&nbsp;splits&nbsp;into&nbsp;at&nbsp;most<br>
-maxsplit&nbsp;words.&nbsp;&nbsp;If&nbsp;sep&nbsp;is&nbsp;not&nbsp;specified,&nbsp;any&nbsp;whitespace&nbsp;string<br>
-is&nbsp;a&nbsp;separator.<br>
-&nbsp;<br>
-(split&nbsp;and&nbsp;splitfields&nbsp;are&nbsp;synonymous)</tt></small></dl>
- <dl><dt><a name="-splitfields"><strong>splitfields</strong></a> = split(s, sep<small><font color="#909090">=None</font></small>, maxsplit<small><font color="#909090">=-1</font></small>)<dd><small><tt><a href="#-split">split</a>(s&nbsp;[,sep&nbsp;[,maxsplit]])&nbsp;-&gt;&nbsp;list&nbsp;of&nbsp;strings<br>
-&nbsp;<br>
-Return&nbsp;a&nbsp;list&nbsp;of&nbsp;the&nbsp;words&nbsp;in&nbsp;the&nbsp;string&nbsp;s,&nbsp;using&nbsp;sep&nbsp;as&nbsp;the<br>
-delimiter&nbsp;string.&nbsp;&nbsp;If&nbsp;maxsplit&nbsp;is&nbsp;given,&nbsp;splits&nbsp;into&nbsp;at&nbsp;most<br>
-maxsplit&nbsp;words.&nbsp;&nbsp;If&nbsp;sep&nbsp;is&nbsp;not&nbsp;specified,&nbsp;any&nbsp;whitespace&nbsp;string<br>
-is&nbsp;a&nbsp;separator.<br>
-&nbsp;<br>
-(split&nbsp;and&nbsp;splitfields&nbsp;are&nbsp;synonymous)</tt></small></dl>
- <dl><dt><a name="-strip"><strong>strip</strong></a>(s)<dd><small><tt><a href="#-strip">strip</a>(s)&nbsp;-&gt;&nbsp;string<br>
-&nbsp;<br>
-Return&nbsp;a&nbsp;copy&nbsp;of&nbsp;the&nbsp;string&nbsp;s&nbsp;with&nbsp;leading&nbsp;and&nbsp;trailing<br>
-whitespace&nbsp;removed.</tt></small></dl>
- <dl><dt><a name="-swapcase"><strong>swapcase</strong></a>(s)<dd><small><tt><a href="#-swapcase">swapcase</a>(s)&nbsp;-&gt;&nbsp;string<br>
-&nbsp;<br>
-Return&nbsp;a&nbsp;copy&nbsp;of&nbsp;the&nbsp;string&nbsp;s&nbsp;with&nbsp;upper&nbsp;case&nbsp;characters<br>
-converted&nbsp;to&nbsp;lowercase&nbsp;and&nbsp;vice&nbsp;versa.</tt></small></dl>
- <dl><dt><a name="-translate"><strong>translate</strong></a>(s, table, deletions<small><font color="#909090">=''</font></small>)<dd><small><tt><a href="#-translate">translate</a>(s,table&nbsp;[,deletions])&nbsp;-&gt;&nbsp;string<br>
-&nbsp;<br>
-Return&nbsp;a&nbsp;copy&nbsp;of&nbsp;the&nbsp;string&nbsp;s,&nbsp;where&nbsp;all&nbsp;characters&nbsp;occurring<br>
-in&nbsp;the&nbsp;optional&nbsp;argument&nbsp;deletions&nbsp;are&nbsp;removed,&nbsp;and&nbsp;the<br>
-remaining&nbsp;characters&nbsp;have&nbsp;been&nbsp;mapped&nbsp;through&nbsp;the&nbsp;given<br>
-translation&nbsp;table,&nbsp;which&nbsp;must&nbsp;be&nbsp;a&nbsp;string&nbsp;of&nbsp;length&nbsp;256.&nbsp;&nbsp;The<br>
-deletions&nbsp;argument&nbsp;is&nbsp;not&nbsp;allowed&nbsp;for&nbsp;Unicode&nbsp;strings.</tt></small></dl>
- <dl><dt><a name="-upper"><strong>upper</strong></a>(s)<dd><small><tt><a href="#-upper">upper</a>(s)&nbsp;-&gt;&nbsp;string<br>
-&nbsp;<br>
-Return&nbsp;a&nbsp;copy&nbsp;of&nbsp;the&nbsp;string&nbsp;s&nbsp;converted&nbsp;to&nbsp;uppercase.</tt></small></dl>
- <dl><dt><a name="-zfill"><strong>zfill</strong></a>(x, width)<dd><small><tt><a href="#-zfill">zfill</a>(x,&nbsp;width)&nbsp;-&gt;&nbsp;string<br>
-&nbsp;<br>
-Pad&nbsp;a&nbsp;numeric&nbsp;string&nbsp;x&nbsp;with&nbsp;zeros&nbsp;on&nbsp;the&nbsp;left,&nbsp;to&nbsp;fill&nbsp;a&nbsp;field<br>
-of&nbsp;the&nbsp;specified&nbsp;width.&nbsp;&nbsp;The&nbsp;string&nbsp;x&nbsp;is&nbsp;never&nbsp;truncated.</tt></small></dl>
-</td></tr></table>
-<p><table width="100%" cellspacing=0 cellpadding=2 border=0>
-<tr bgcolor="#55aa55">
-<td colspan=3 valign=bottom><small><small>&nbsp;<br></small></small
-><font color="#ffffff" face="helvetica, arial"><big><strong>Data</strong></big></font></td></tr>
-
-<tr><td bgcolor="#55aa55"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;&nbsp;</td>
-<td width="100%"><strong>_StringType</strong> = &lt;type 'string'&gt;<br>
-<strong>__file__</strong> = r'c:\Python21\Lib\string.pyc'<br>
-<strong>__name__</strong> = 'string'<br>
-<strong>_idmap</strong> = '<font color="#c040c0">\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f</font> !"#$%&amp;<font color="#c040c0">\'</font>()*+,-./...<font color="#c040c0">\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff</font>'<br>
-<strong>_idmapL</strong> = None<br>
-<strong>digits</strong> = '0123456789'<br>
-<strong>hexdigits</strong> = '0123456789abcdefABCDEF'<br>
-<strong>letters</strong> = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'<br>
-<strong>lowercase</strong> = 'abcdefghijklmnopqrstuvwxyz'<br>
-<strong>octdigits</strong> = '01234567'<br>
-<strong>printable</strong> = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&amp;<font color="#c040c0">\'</font>()*+,-./:;&lt;=&gt;?@[<font color="#c040c0">\\</font>]^_`{|}~ <font color="#c040c0">\t\n\r\x0b\x0c</font>'<br>
-<strong>punctuation</strong> = '!"#$%&amp;<font color="#c040c0">\'</font>()*+,-./:;&lt;=&gt;?@[<font color="#c040c0">\\</font>]^_`{|}~'<br>
-<strong>uppercase</strong> = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'<br>
-<strong>whitespace</strong> = '<font color="#c040c0">\t\n\x0b\x0c\r</font> '</td></tr></table>
-</body></html> \ No newline at end of file
diff --git a/sandbox/tibs/pysource/notes/thoughts.txt b/sandbox/tibs/pysource/notes/thoughts.txt
deleted file mode 100644
index 59691717b..000000000
--- a/sandbox/tibs/pysource/notes/thoughts.txt
+++ /dev/null
@@ -1,170 +0,0 @@
-Thoughts on pysource
-====================
-
-:Author: Tibs
-:Date: 19 Sep 2002
-
-..
-
- [This is the contents of an email sent from Tibs to me, to tie up
- -- or at least identify -- loose ends. When Tibs writes "you",
- he's referring to me. It is published with Tibs' permission. I
- mostly agree with what Tibs has written. I've added my own notes,
- indented in square brackets, like this one.
-
- --David Goodger]
-
-Well, having looked back at the pysource sources, I'm confirmed
-in my opinion that, if I were to start work on the project again,
-I would probably start a new version of pysource from scratch,
-using what I have learned (essentially, the content of visit.py),
-and taking advantage of all the new technology that is in the
-modern DOCUTILS.
-
-Thus I would (at least):
-
-1. produce a "frontend" using Optik
-2. rewrite visit.py more neatly
-3. construct DOCUTILS nodes to match pysource.dtd
-4. *possibly* meld those into the classes in visit.py
- (but possibly not - some of the stuff in visit.py
- seems to me to be, of necessity, a bit messy as it
- is constructing stuff, and thus it may be premature
- to "DOCUTILS" it before it is necessary).
-5. produce an example transform to amend the Python
- specific DOCUTILS tree into a generic DOCUTILS
- tree.
-
-That's a fair amount of work, and I'm not convinced that I can
-find the sustained effort [1]_, especially if you might be
-willing to take the task on (and if I would have been refactoring
-anyway, a whole different head may be a significant benefit).
-
-.. [1] I believe that's called "British understatement".
-
-Some comments on pysource.txt and pysource.dtd
-----------------------------------------------
-
-I believe that a <docstring> node is a Good Thing. It's a natural
-construct (if one believes that the other nodes are good things
-as well!), and it allows the "transform" of the Python specific
-tree to be done more sensibly.
-
- [I think I finally understand what Tibs is getting at here. I
- thought he meant to have a <docstring> node in an otherwise
- standard Docutils doctree, which just contained the raw docstring.
- Instead, I believe he means that the Python-specific Docutils
- doctree elements like <class_section> and
- <module_section> (see pysource.dtd), should each have a <docstring>
- element which contains ``%structure.model;``, instead of the
- current ``%structure.model;`` directly inside the element. In
- other words, a <docstring> element would be a simple container for
- all the parsed elements of the docstring. On second thought, each
- Python-specific section element would still have to have
- ``%structure.model;``, in order to contain subsections. A
- <package_section> would contain <module_section>s, which would
- contain <class_section>s, and so on.
-
- So a <docstring> element may be useful as a convenience to
- transforms. It would be a trivial change anyhow.
-
- The initial (internal) data structure resulting from the parsing
- of Python modules & packages is a completely different beast. It
- should contain <docstring> nodes, along with <package>, <module>,
- <class>, etc., nodes. But these should *not* be subclasses of
- docutils.nodes.Node, and this tree should not be a "Docutils
- document tree". It should be a separate, parallel structure.
- Document tree nodes (docutils.nodes.Node objects) are not suited
- for this work.
-
- --DG]
-
-I recommend some initial "surgery" on the initial parse tree to
-make finding the docstrings for nodes easier.
-
-I reckon that one produces a Python-specific doctree, and then
-chooses one of several transforms to produce generic doctrees.
-
-By the way, I still vote for "static" introspection - that is,
-without actually importing the module. It does limit what one can
-do in some respects, but there are modules one might want to
-document that one does not wish to import (and indeed, at work we
-have some Python files that essentially cannot be introspected in
-this manner with any ease - they are "designed" to be imported by
-other modules after ``sys.path`` has been mangled suitably, and
-just don't work stand-alone).
-
-I've tried to expand out the ideas you had on how the "pysource"
-tool should work below.
-
- although it occurs to me that this is all terribly obvious,
- really. Oh well...
-
-The pysource tool
------------------
-
-The "input mode" should be the "Python Source Reader".
-
- You can see where I'm starting from in pysource.txt.
-
-This produces, as its output, a Python-specific doctree,
-containing extra nodes as defined in pysource.dtd (etc.).
-
-One of the tasks undertaken by the Python Source Reader is to
-decide what to do with docstrings. For each Python file, it
-discovers (from ``__docformat__``) if the input parser is
-"reStructuredText". If it is, then the contents of each docstring
-in that file will be parsed as such, including sorting out
-interpreted text (i.e., rendering it into links across the tree).
-If it is not, then each docstring will be treated as a literal
-block.
-
- This admits the posibility of adding other parsers *for
- docstrings* at a later date - which I suspect is how HappyDoc
- does it. It is just necessary to publicise the API for the
- Docstring class, and then someone else can provide alternate
- plugins.
-
-The output of the Python Source Reader is thus a Python-specific
-doctree, with all docstrings fully processed (as appropriate),
-and held inside <docstring> elements.
-
-The next stage is handled by the Layout Transformer.
-
- [What I call "stylist transforms". --DG]
-
-This determines the layout of the document to be produced - the
-*kind* or *style* of output that the user wants (e.g., PyDoc
-style, LibRefMan style, generic docutils style, etc.).
-
-Each layout is represented by a class that walks the
-Python-specific doctree, replacing the Python-specific nodes with
-appropriate generic nodes. The output of the Layout Transformer
-is thus a generic doctree.
-
-The final stage is thus a normal DOCUTILS Writer - since it is
-taking input that is a generic doctree, this makes perfect
-sense. This also means that we get maximum leverage from existing
-Writers, which is essential (not just a Good Thing).
-
-As you point out, some layouts will probably only be appropriate
-for some output formats. Well, that's OK. On the other hand, if
-the output of the Layout stage *is* a generic doctree, we're not
-likely to get fatal errors by putting it through the wrong
-Writer, so we needn't worry too much.
-
-Thus one might envisage a command line something like::
-
- pysource --layout:book --format:html this_module
-
-Of course, other command line switches would be options for
-particular phases (e.g., to use frames or not for HTML output). I
-can see wanting a series of configuration files that one could
-reference, to save specifying lots of switches.
-
-One specific thing to be decided, particularly for HTML, is
-whether one is outputting a "cluster" of files (e.g., as javadoc
-does). I reckon this can be left for later on, though (as can
-such issues as saying "other interesting sources are *over
-there*, so reference them if you can" - e.g., the Python
-library).
diff --git a/sandbox/tibs/pysource/pysource.py b/sandbox/tibs/pysource/pysource.py
deleted file mode 100755
index a62c96ebb..000000000
--- a/sandbox/tibs/pysource/pysource.py
+++ /dev/null
@@ -1,262 +0,0 @@
-#! /usr/bin/env python
-"""A simple command line interface for the pysource package
-
-This will become more interesting later on...
-"""
-
-import os
-import sys
-import getopt
-
-import docutils.nodes
-import docutils.utils
-
-# Local modules
-import utils
-import visit
-import html
-
-import transform
-
-__docformat__ = "reST"
-
-
-# ----------------------------------------------------------------------
-def rest_document(filename):
- """Return an reST document.
- """
-
- from docutils.parsers.rst import Parser
-
- file = open(filename)
- try:
- text = file.read()
- finally:
- file.close()
-
- parser = Parser()
- docroot = docutils.utils.new_document()
- parser.parse(text,docroot)
- return docroot
-
-
-# ----------------------------------------------------------------------
-# I don't much like the Unix command line style (I always thought the
-# VMS approach was much more flexible and sensible), but it *does* seem
-# to be what people expect these days...
-
-options = [
- # long option, short, description
- ("verbose", "v", "Report on progress in more detail"),
- ("quiet", "q", "Suppress normal progress messages"),
- ("text", "t", "The input file is a plain (text) reST file"),
- ("show", "s", "Output basic information about the input"),
- ("ast", "a", "Output a representation of the AST"),
- ("xml", "x", "Output an XML representation of the input"),
- ("html", "h", "Output an HTML representation of the input [default]"),
- ("pretty", "p", "Output a 'pretty' representation of the input"),
- ("doctest", "d", "Treat a reST file as doctest input."),
- ("help", "h", "Show 'help' information"),
- ("new", "n", "Use David Goodger's HTML Writer (sort of)"),
- ("stdout", "", "Write output to stdout, instead of a file"),
- ]
-
-def print_usage():
- docstring = visit.Docstring(main.__doc__)
- docstring.show(sys.stdout)
- print
- print " <switches> are:"
- print
- for longopt, shortopt, description in options:
- if shortopt:
- print " -%s, --%-9s %s"%(shortopt,longopt,description)
- else:
- print " --%-9s %s"%(longopt,description)
-
-def main():
- """The command line interface to docutil's Python documentation extractor.
-
- Usage: ``pysource.py <switches> <inpath> [<outfile>]``
-
- <inpath> is the path to a package or module.
-
- <outfile> is the path to the output file. If it's not given, then
- output will be written to a file with the same name as the input
- file, but defaulting to the current directory, and with extension
- derived from the type of output:
-
- - show -> ``.show``
- - ast -> ``.ast``
- - xml -> ``.xml``
- - html -> ``.html``
- - pretty -> ``.pretty``
-
- (unless --stdout is requested). The default is --html.
-
- Note that progress messages (and ``verb`` information) are written
- to ``sys.stderr``.
- """
-
- if len(sys.argv) <= 1:
- print "Not enough arguments"
- print_usage()
- return
-
- shortopts = ''.join([option[1] for option in options])
- longopts = [option[0] for option in options]
- try:
- opts, args = getopt.getopt(sys.argv[1:], shortopts, longopts)
- except getopt.GetoptError,detail:
- print "Problem with options:",detail
- print_usage()
- return
-
- verbose = 0
- quiet = 0
- input_format = "python"
- output_format = "html"
- want_docutilstree = 1
- new_writer = 0
- write_stdout = 0
-
- for opt, arg in opts:
- if opt in ["-?","--help"]:
- print_usage()
- return
- elif opt in ["-n","--new"]:
- new_writer = 1
- output_format = "html"
- print >>sys.stderr, "Using new HTML Writer"
- elif opt in ["-v","--verbose"]:
- verbose = 1
- elif opt in ["-q","--quiet"]:
- quiet = 1
- elif opt in ["-t","--text"]:
- input_format = "text"
- elif opt in ["-s","--show"]:
- output_format = "show"
- want_docutilstree = 0
- elif opt in ["-a","--ast"]:
- output_format = "ast"
- want_docutilstree = 0
- elif opt in ["-x","--xml"]:
- output_format = "xml"
- elif opt in ["-h","--html"]:
- output_format = "html"
- elif opt in ["-d","--doctest"]:
- output_format = "doctest"
- elif opt in ["-p","--pretty"]:
- output_format = "pretty"
- elif opt == "--stdout":
- write_stdout = 1
- else:
- raise getopt.GetoptError, "getopt should have saved us!"
-
- if len(args) == 0 or len(args) > 2:
- print "Please specify an input and an (optional) output"
- print_usage()
- return
-
- if input_format == "text" and \
- output_format not in ["xml","html","pretty","doctest"]:
- print "--text only supports --xml, --html, --pretty or --doctest"
- print_usage()
- return
-
- if input_format == "text" and output_format == "doctest" \
- and len(args) == 2:
- print "--doctest does not accept an output file"
- # Should it?
- print_usage()
- return
-
- if write_stdout and len(args) == 2:
- print "It doesn't make sense to specify --stdout and an output file"
- print_usage()
- return
-
- filename = args[0]
- if len(args) == 2:
- if not quiet:
- print >>sys.stderr, "... Output will go to",args[1]
- outstream = open(args[1],"w")
- elif write_stdout:
- if not quiet:
- print >>sys.stderr, "... Output will go to standard output"
- outstream = sys.stdout
- else:
- head,tail = os.path.split(filename)
- base,ext = os.path.splitext(tail)
- outname = "%s.%s"%(base,output_format)
- if not quiet:
- print >>sys.stderr, "... Output will go to",outname
- outstream = open(outname,"w")
-
- try:
- if output_format == "doctest":
- from doctest import Tester
- if not quiet: print >>sys.stderr, "*** Doctesting the document"
- t = Tester(globs={},verbose=verbose)
- (fail,total) = t.runstring(open(filename).read(),filename)
- if not quiet and not verbose:
- print >>sys.stderr, "*** ",
- if fail:
- print "%d of"%fail,
- if total == 1:
- print "1 example",
- else:
- print "%d examples"%total,
- if fail:
- print "failed"
- else:
- print "passed"
- elif input_format == "text":
- if not quiet: print >>sys.stderr, "*** Making the document"
- document = rest_document(filename)
- else:
- if os.path.isdir(filename):
- print >>sys.stderr, "*** Parsing the Python package",filename
- thing = visit.Package(None, filename)
- else:
- print >>sys.stderr, "*** Parsing the Python file",filename
- thing = visit.Module(None, filename)
-
- if want_docutilstree:
- if not quiet:
- print >>sys.stderr, "*** Making the document"
- with_groups = not new_writer
- process = transform.Process(with_groups)
- document = process(thing)
-
- if output_format == "show":
- thing.show(outstream)
- elif output_format == "ast":
- thing.show_ast(outstream)
- print
- elif output_format == "pretty":
- outstream.write(document.pformat(indent=" "))
- elif output_format == "xml":
- if not quiet: print >>sys.stderr, "*** Producing a DOM tree"
- domtree = document.asdom()
- if not quiet: print >>sys.stderr, " Writing XML"
- domtree.writexml(outstream,indent="", addindent=" ",newl="\n")
- elif output_format == "html":
- if not quiet: print >>sys.stderr, "*** Writing HTML"
- if new_writer:
- from docutils.writers.html4css1 import Writer
- writer = Writer()
- writer.write(document,outstream)
- elif input_format == "text":
- writer = html.Writer()
- writer(document,outstream)
- else:
- writer = html.PythonWriter()
- writer(document,outstream)
- finally:
- if outstream != sys.stdout:
- outstream.close()
-
-
-# ----------------------------------------------------------------------
-if __name__ == "__main__":
- main()
diff --git a/sandbox/tibs/pysource/rjhack.py b/sandbox/tibs/pysource/rjhack.py
deleted file mode 100755
index 6046312ac..000000000
--- a/sandbox/tibs/pysource/rjhack.py
+++ /dev/null
@@ -1,58 +0,0 @@
-#!/usr/bin/env python
-
-# Author: Richard Jones
-# Contact: richard@users.sourceforge.net
-# Revision: $Revision$
-# Date: $Date$
-# Copyright: This module has been placed in the public domain.
-
-"""
-A front end to the Docutils Publisher, taking Python source and producing HTML.
-"""
-
-import os, locale
-try:
- locale.setlocale(locale.LC_ALL, '')
-except:
- pass
-
-import visit, transform
-
-from docutils.parsers.rst import Parser
-class SourceParser(Parser):
- supported = ('pysource',)
- settings_spec = (
- 'PySource Parser Options',
- None,
- (('Be verbose while parsing', ['--verbose-parse'],
- {'action': 'store_true'}),
- )) + Parser.settings_spec
- def parse(self, filename, document):
- if os.path.isdir(filename):
- thing = visit.Package(document.settings, filename)
- else:
- thing = visit.Module(document.settings, filename)
- process = transform.Process(with_groups=0, document=document)
- process(thing)
-
-from docutils.readers import Reader
-class SourceReader(Reader):
- def read(self, source, parser, settings):
- self.source = source
- if not self.parser:
- self.parser = parser
- self.settings = settings
- # we want the input as the filename, not the file content
- self.source.source.close()
- self.input = self.source.source_path
- self.parse()
- return self.document
-
-from docutils.core import publish_cmdline, default_description
-description = ('Generates (X)HTML documents from Python sources. '
- + default_description)
-parser = SourceParser()
-reader = SourceReader(parser, 'pysource')
-publish_cmdline(reader=reader, parser=parser, writer_name='html',
- description=description)
-
diff --git a/sandbox/tibs/pysource/test/readme.txt b/sandbox/tibs/pysource/test/readme.txt
deleted file mode 100644
index a6af4576d..000000000
--- a/sandbox/tibs/pysource/test/readme.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-Files in the ``test`` directory
--------------------------------
-
-This directory is intended to contain various test file. They are (hopefully)
-named in a consistent manner:
-
-README.txt
- This file.
-
-``*.rtxt``
- Sample reST text files, suitable for checking odd things.
-
-``*.py``
- Sample Python test files, ditto.
-
-``*.doctest``
- Files that contain "semiliterate testing" [1]_ -- that is,
- descriptive text (written with reST) surrounding doctest blocks.
- The idea is that these files should be passed to (for instance)
- pydps.py (or whatever it is called at the moment) to be tested by
- Tim Peters' doctest - for instance::
-
- pydps/pydps.py --text --doctest simple.doctest
-
-
-
-.. [1] a semi-lame reference to literate programming, I'm afraid.
diff --git a/sandbox/tibs/pysource/test/test.doctest b/sandbox/tibs/pysource/test/test.doctest
deleted file mode 100644
index bc91115ad..000000000
--- a/sandbox/tibs/pysource/test/test.doctest
+++ /dev/null
@@ -1,12 +0,0 @@
-The following is some Python code:
-
- >>> a = 1
- >>> a
- 1
-
-and here is some more:
-
- >>> a + 1
- 3
-
-and that's all.
diff --git a/sandbox/tibs/pysource/test/test.py b/sandbox/tibs/pysource/test/test.py
deleted file mode 100755
index b3e380526..000000000
--- a/sandbox/tibs/pysource/test/test.py
+++ /dev/null
@@ -1,124 +0,0 @@
-"""A simple test file for input to ast-mining.py.
-
-But it isn't a "raw" string, so:
-
- \\*escape* \\`with` "\\\\"
-"""
-
-__docformat__ = "reST"
-
-import string
-
-one = 1
-
-"""Documentation after `one` (intervening blank line)"""
-
-two,three = 2,3
-"""Documenatation after ``two,three=2,3``"""
-
-four,five = two,three
-
-six = [four,five]
-"""Documentation after ``six=[four,five]``"""
-
-global gmodule
-gmodule = 1
-"""Global at the module level"""
-
-def func(a,b=1,c='jim',d=None,e=[],f={'a':1},g=(1,2,3)):
- r"""Function at the module level
-
- This *is* a "raw" string, so:
-
- \*escape* \`with` "\\"
- """
-
- from string import lstrip,rstrip
-
- a = 3
-
- global gfunc
- gfunc = 1
- """Global referenced only within `func()`"""
-
- global one
- one = 2
-
- class InFunc:
- pass
-
- def infunc():
- """Function defined inside function `func()`"""
- global ginner
- ginner = 1
- """Global referenced only within `infunc()`"""
-
- class Silly:
- pass
-
- def silly_fn():
- pass
-
-def func2(a,*args,**kargs):
- pass
-
-def func3((a,b,c),d):
- pass
-
-class Fred:
- """Class at the module level."""
-
- a = 1
- """Documentation for class value `a`"""
-
- global gclass
- gclass = 2
- """Global referenced only within `Fred`"""
-
- def __init__(self):
- """Initialisation for `Fred`"""
- self.b = 2
- """`self.b` within `Fred.__init__()`"""
-
- c = 3
- """Local variable within `Fred.__init__()`"""
-
- global gmeth
- gmeth = 3
- """Global referenced only within a method"""
-
- global gagain
- gagain = 3
-
- class Insider:
- """Class defined inside `Fred.__init__()`"""
-
- a = 'jim'
- """Local name within class inside `Fred.__init__()`"""
-
- global gclass2
- gclass2 = 4
- """Global referenced only within a class within a method"""
-
- global gunused
- global gagain
-
- def fred(self):
- global gunused2,gfunc2
- gfunc2 = 5
- """Global referenced only within a method in a
- class in a method
- """
-
- def fredinner():
- global ginner2
- global gagain
- ginner2 = 6
- gagain = 6
-
- infredinner = 7
-
-class Jim(Fred):
- pass
-
-
diff --git a/sandbox/tibs/pysource/test/test.rtxt b/sandbox/tibs/pysource/test/test.rtxt
deleted file mode 100644
index f28a3d4e2..000000000
--- a/sandbox/tibs/pysource/test/test.rtxt
+++ /dev/null
@@ -1,442 +0,0 @@
-pydps test document
-===================
-
-:Author: Tibs
-:Version: 0.1
-:Eggs: Green
-:Ham: Green
-
-This is intended to be a simple test document, with "something of everything".
-It is *not* intended to trawl for *problems*, but just to check I've got the
-writing out of just about everything supported in the HTML writer.
-
- :Author: Tibs
- :Version: 0.1
- :Eggs: Green
- :Ham: Green
- :Parameter i: integer
-
-Lists
------
-1. A list
-2. Some more
-3.
-
- * What's this?
- - and this?
- + and this?
-
-i. And this is Roman
-
-a. And this is alpha
-
-A. And so is this
-
-I. What is this?
-
-.. Just a comment, honest.
- That's all.
-
-A title
- and some text.
-And another
- and more text.
-
-Short options:
-
--a option a
-
--b file option b
-
--cname option c
-
-Long options:
-
---aaaa option aaaa
---bbbb=file option bbbb
---cccc name option cccc
---d-e-f-g option d-e-f-g
---h_i_j_k option h_i_j_k
-
-VMS/DOS-style options:
-
-/A option A
-/B file option B
-/Cstring option C
-
-Mixed short, long, and VMS/DOS options:
-
--a option a
---bbbb=file option bbbb
-/C option C
---dddd name option dddd
--e string option e
-/F file option F
-
-Aliased options:
-
--a, --aaaa, /A option a, aaaa, A
--b file, --bbbb=file, /B file option b, bbbb, B
-
-Multiple lines in descriptions, aligned:
-
--a option a, line 1
- line 2
--b file option b, line 1
- line 2
-
-Multiple lines in descriptions, not aligned:
-
--a option a, line 1
- line 2
--b file option b, line 1
- line 2
-
-Some edge cases:
-
---option=arg arg too many arguments
-
---option=arg=arg too many arguments
-
--aletter arg too many arguments (-a letter)
-
-/Aletter arg too many arguments (/A letter)
-
--a=b can't use = for short arguments
-
-/A=b can't use = for DOS/VMS arguments?
-
---option= argument missing
-
---=argument option missing
-
--- everything missing
-
-- this should be a bullet list item
-
-+ bullet
-
-.. Comments swallow up all indented text following.
-
- (Therefore this is not a) block quote.
-
-- bullet
-
- If we want a block quote after this bullet list item,
- we need to use an empty comment:
-
-..
-
- Block quote.
-
-Other blocks
-------------
-
-::
-
- Anonymous literal block
-
-This is a literal block::
-
- This here.
-
-And we don't need colons ::
-
- Not really.
-
-Of course, **I** like Python:
-
- >>> print " Indented block & output."
- Indented block & output.
-
-Or maybe I don't::
-
- >>> print " Indented block & output."
- Indented block & output.
-
-Footnotes
----------
-
-Autonumbered footnotes
-......................
-[#]_ is the first auto-numbered footnote reference.
-[#]_ is the second auto-numbered footnote reference.
-
-.. [#] Auto-numbered footnote 1.
-.. [#] Auto-numbered footnote 2.
-.. [#] Auto-numbered footnote 3.
-
-[#]_ is the third auto-numbered footnote reference.
-
-Autonumbered and named footnotes
-................................
-[#six]_ is a reference to the sixth auto-numbered footnote.
-
-.. [#four] Fourth auto-numbered footnote.
-.. [#five] Fifth auto-numbered footnote.
-.. [#six] Sixth auto-numbered footnote.
-
-[#five]_ is a reference to the fifth auto-numbered footnote.
-[#four]_ is a reference to the fourth auto-numbered footnote.
-[#six]_ is another reference to the sixth auto-numbered footnote.
-
-Here are some internal cross-references to the implicit targets
-generated by the footnotes: four_, five_, six_.
-
-Mixed anonymous and labelled auto-numbered footnotes
-....................................................
-[#ten]_ should be 10, [#]_ should be 7,
-[#]_ should be 9, [#]_ is one too many,
-[#eight]_ should be 8, and [#twelve]_ doesn't exist,
-nor does [#eleven]_.
-
-.. [#] Auto-numbered footnote 7.
-.. [#eight] Auto-numbered footnote 8.
-.. [#] Auto-numbered footnote 9.
-.. [#ten] Auto-numbered footnote 10.
-.. [#eleven] Auto-numbered footnote 11.
-.. [#eleven] Auto-numbered footnote 11 again (duplicate).
-
-Inline stuff
-------------
-(**strong**) but not (**) or '(** ' or x**2 or \\**kwargs or **
-
-(however, '**kwargs' will trigger a warning and may be problematic)
-
-Strong asterisk: *****
-
-Strong double asterisk: ******
-
-``literal``
-``lite\\ral``
-
-``literal ``TeX quotes'' & \\backslash`` but not "``" or ``
-
-(however, ``standalone TeX quotes'' will trigger a warning
-and may be problematic)
-
-Find the ```interpreted text``` in this paragraph!
-
-`interpreted`
-:role:`interpreted`
-
-`interpreted` but not \\`interpreted` [`] or ({[`] or [`]}) or `
-
-`interpreted`-text `interpreted`: text `interpreted`:text `text`'s interpreted
-
-http://www.standalone.hyperlink.com
-
-one-slash-only:/absolute.path
-
-mailto:someone@somewhere.com
-
-news:comp.lang.python
-
-An email address in a sentence: someone@somewhere.com.
-
-ftp://ends.with.a.period.
-
-(a.question.mark@end?)
-
-Tables
-------
-
-+-------------------------------------+
-| A table with one cell and one line. |
-+-------------------------------------+
-
-+-----------------------+
-| A malformed table. |
-+-----------------------+
-
-+------------------------+
-| A well-formed | table. |
-+------------------------+
-
-+------------------------+
-| This +----------+ too! |
-+------------------------+
-
-+--------------------------+
-| A table with three rows, |
-+------------+-------------+
-| and two | columns. |
-+------------+-------------+
-| First and last rows |
-| contain column spans. |
-+--------------------------+
-
-+------------+-------------+---------------+
-| A table | two rows in | and row spans |
-| with three +-------------+ to left and |
-| columns, | the middle, | right. |
-+------------+-------------+---------------+
-
-+------------+-------------+---------------+
-| A table | | two rows in | and funny |
-| with 3 +--+-------------+-+ stuff. |
-| columns, | the middle, | | |
-+------------+-------------+---------------+
-
-+-----------+-------------------------+
-| W/NW cell | N/NE cell |
-| +-------------+-----------+
-| | Middle cell | E/SE cell |
-+-----------+-------------+ |
-| S/SE cell | |
-+-------------------------+-----------+
-
-+--------------+-------------+
-| A bad table. | |
-+--------------+ |
-| Cells must be rectangles. |
-+----------------------------+
-
-+-------------------------------+
-| A table with two header rows, |
-+------------+------------------+
-| the first | with a span. |
-+============+==================+
-| Two body | rows, |
-+------------+------------------+
-| the second with a span. |
-+-------------------------------+
-
-+-------------------------------+
-| A table with two head/body |
-+=============+=================+
-| row | separators. |
-+=============+=================+
-| That's bad. | |
-+-------------+-----------------+
-
-The traditional:
-
- +------------------------+------------+----------+----------+
- | Header row, column 1 | Header 2 | Header 3 | Header 4 |
- +========================+============+==========+==========+
- | body row 1, column 1 | column 2 | column 3 | column 4 |
- +------------------------+------------+----------+----------+
- | body row 2 | Cells may span columns. |
- +------------------------+------------+---------------------+
- | body row 3 | Cells may | - Table cells |
- +------------------------+ span rows. | - contain |
- | body row 4 | | - body elements. |
- +------------------------+------------+---------------------+
-
-+-----------------+--------+
-| A simple table | cell 2 |
-+-----------------+--------+
-| cell 3 | cell 4 |
-+-----------------+--------+
-No blank line after table.
-
-+-----------------+--------+
-| A simple table | cell 2 |
-+-----------------+--------+
-| cell 3 | cell 4 |
-+-----------------+--------+
- Unexpected indent and no blank line after table.
-
-+------------------------------+
-| This table contains another. |
-| |
-| +-------------------------+ |
-| | A table within a table. | |
-| +-------------------------+ |
-+------------------------------+
-
-+------------------+--------+
-| A simple table | |
-+------------------+--------+
-| with empty cells | |
-+------------------+--------+
-
-Links and so on
----------------
-.. _target:
-
-(internal hyperlink)
-
-.. _one-liner: http://structuredtext.sourceforge.net
-
-.. _starts-on-this-line: http://
- structuredtext.
- sourceforge.net
-
-.. _entirely-below:
- http://structuredtext.
- sourceforge.net
-
-.. _target1: Not a proper hyperlink target
-
-.. _a long target name:
-
-.. _`a target name: including a colon (quoted)`:
-
-.. _a target name\: including a colon (escaped):
-
-.. _target2: http://www.python.org/
-
-(indirect external hyperlink)
-
-Duplicate indirect links (different URIs):
-
-.. _target3: first
-
-.. _target3: second
-
-Duplicate indirect links (same URIs):
-
-.. _target4: first
-
-.. _target4: first
-
-Directives
-----------
-.. Attention:: Directives at large.
-
-.. Note:: This is a note.
-
-.. Tip:: 15% if the
- service is good.
-
-- .. WARNING:: Strong prose may provoke extreme mental exertion.
- Reader discretion is strongly advised.
-- .. Error:: Does not compute.
-
-.. Caution::
-
- Don't take any wooden nickels.
-
-.. DANGER:: Mad scientist at work!
-
-.. Important::
- - Wash behind your ears.
- - Clean up your room.
- - Call your mother.
- - Back up your data.
-
-.. image:: images/ball.gif
-
-.. image::
- picture.png
- [height=100 width=200 scale=50]
-
-.. figure:: picture.png
-
- A picture with a caption.
-
-.. figure:: picture.png
-
- A picture with a caption and a legend.
-
- +-----------------------+-----------------------+
- | Symbol | Meaning |
- +=======================+=======================+
- | .. image:: tent.png | Campground |
- +-----------------------+-----------------------+
- | .. image:: waves.png | Lake |
- +-----------------------+-----------------------+
- | .. image:: peak.png | Mountain |
- +-----------------------+-----------------------+
diff --git a/sandbox/tibs/pysource/test/testassign.py b/sandbox/tibs/pysource/test/testassign.py
deleted file mode 100755
index e4d70a356..000000000
--- a/sandbox/tibs/pysource/test/testassign.py
+++ /dev/null
@@ -1,12 +0,0 @@
-class Jim:
-
- def __init__(self):
- a = 1
- a = [2,3]
- a,b = 4,5
- a,b = [6,7]
- a,self.a = 8,9
- a = b = self.a = 10
- a,b = c,d = 11,12
- self.a,self.b = 13,14
- self.a = self.b = 15
diff --git a/sandbox/tibs/pysource/test/testfunc.py b/sandbox/tibs/pysource/test/testfunc.py
deleted file mode 100755
index 4a887b098..000000000
--- a/sandbox/tibs/pysource/test/testfunc.py
+++ /dev/null
@@ -1,34 +0,0 @@
-# Stuff needed to make the examples compile...
-class Fred:
- def __getitem__(self,index):
- pass
-a = Fred()
-b = [1,2,3,4]
-d = Fred()
-
-def func1(a,b=1,c='jim',d=None,e=[],f={'a':1,a:1},g=(1,2,3)):
- pass
-
-def func2(a,*args,**kargs):
- pass
-
-def func2a(a,*args):
- pass
-
-def func2b(a,**kargs):
- pass
-
-def func3((a,b,c),d):
- pass
-
-def func4(a=a,b=Fred,c=Fred()):
- pass
-
-def func5(a=[x for x in [1,2,3] if x > 2],
- b=[(x,y) for x in [1,2,3] for y in [3,4,5]]):
- pass
-
-def func6(a=b[1:2],c=d[1,4:6,...,8:9:10],
- e=lambda x: x*2,
- f=lambda x,a=a: func5(x,a)):
- pass
diff --git a/sandbox/tibs/pysource/test/testinterpreted.py b/sandbox/tibs/pysource/test/testinterpreted.py
deleted file mode 100755
index 00eb59311..000000000
--- a/sandbox/tibs/pysource/test/testinterpreted.py
+++ /dev/null
@@ -1,44 +0,0 @@
-"""Test interpreted text
-
-This module (`testinterpreted`) contains one :class:`Fred`
-(and one hopes `Fred` will also work) and a function *and*
-a method called `fred`.
-
-NB: the above sentence *should*, when transformed into HTML
-or some other output format, hopefully, contain text something
-like::
-
- contains one class Fred
-
-i.e., the ``:class:`Fred``` should probably cause the "insertion"
-of the word "class". Or so I think.
-""" #'
-
-__docformat__ = "reST"
-
-class Fred:
- """This class (`Fred`), in :module:`testinterpreted`, contains
- a method `fred`.
- """
-
- jim = None
- """A class value, a default.
- """
-
- def fred(self):
- """This method (`fred`) is in class `Fred`
- """
- fred = 3
- """This name (`fred`) is in :function:`fred` in class `Fred`.
- """
-
-def fred(fred):
- """This function (:function:`fred`) is *not* in class `Fred`.
-
- It has one argument, :parameter:`fred`.
-
- If I just say `fred`, what *should* that resolve to?
- """
- fred.jim = 3
- """We assume that `fred` must be something with a `jim` attribute...
- """
diff --git a/sandbox/tibs/pysource/test/testinterpreted2.py b/sandbox/tibs/pysource/test/testinterpreted2.py
deleted file mode 100755
index 59dac777a..000000000
--- a/sandbox/tibs/pysource/test/testinterpreted2.py
+++ /dev/null
@@ -1,37 +0,0 @@
-"""
-This is the example from David Goodger's DPS document pysource-reader.txt.
-"""
-
-__docformat__ = "restructuredtext"
-
-class Keeper(Storer):
-
- """
- Extend `Storer`. Class attribute `instances` keeps track of
- the number of `Keeper` objects instantiated.
- """
-
- instances = 0
- """How many `Keeper` objects are there?"""
-
- def __init__(self):
- """
- Extend `Storer.__init__()` to keep track of instances.
-
- Keep count in `self.instances` and data in `self.data`.
- """
- Storer.__init__(self)
- self.instances += 1
-
- self.data = []
- """Store data in a list, most recent last."""
-
- def storedata(self, data):
- """
- Extend `Storer.storedata()`; append new `data` to a list
- (in `self.data`).
-
- Use :method:`Keeper.storedata` to store the object's data in
- `Keeper.data`:instance_attribute:.
- """
- self.data = data
diff --git a/sandbox/tibs/pysource/test/testsimp.py b/sandbox/tibs/pysource/test/testsimp.py
deleted file mode 100755
index 7dfeb4202..000000000
--- a/sandbox/tibs/pysource/test/testsimp.py
+++ /dev/null
@@ -1,12 +0,0 @@
-a = 'b'
-class Fred:
- """A *silly* demonstration."""
-
- def __init__(self, b=1, c='jim', d=None, f={'a':1,a:1},
- g=[x for x in [1,2,3] if x > 2]):
- """Initialise ourselves."""
- self.list = g
-
- def __call__(self,a):
- """Call ourselves."""
- pass
diff --git a/sandbox/tibs/pysource/test/testyield.py b/sandbox/tibs/pysource/test/testyield.py
deleted file mode 100755
index e3fd1d2d0..000000000
--- a/sandbox/tibs/pysource/test/testyield.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from __future__ import generators
-from string import lower as lll
-from string import lower as lll, upper as uuu, lower, lower as xxx
-
-def fred():
- a = 1
- yield a
-
diff --git a/sandbox/tibs/pysource/transform.py b/sandbox/tibs/pysource/transform.py
deleted file mode 100755
index f93f17ed4..000000000
--- a/sandbox/tibs/pysource/transform.py
+++ /dev/null
@@ -1,358 +0,0 @@
-"""Transfer the structure from visit.py into a DOCUTILS node tree.
-
-TODO: ensure that the encoding of individual items makes sense.
-
-This should probably be using David's new mechanisms from the docutils module
-to build the DOCUTILS tree - but they were written after this was coded, and
-I've still to investigate them.
-"""
-
-import string
-
-import docutils.nodes
-import docutils.utils
-
-import visit
-import utils
-import buildtree
-
-__docformat__ = "reST"
-
-
-# ----------------------------------------------------------------------
-class Process:
- """The infrastucture that knows how to produce our DOCUTILS node tree.
- """
-
- def __init__(self, with_groups=1, document=None):
- """Instantiate our transformation to a DOCUTILS tree.
-
- At the moment, whilst we are considering both my own old HTML
- output and also moving towards David Goodger's DOCUTILS HTML output,
- we have the ``with_groups`` argument - if this is false then
- buildtree will not output "group" elements...
- """
- self.current_module = None
- self.dps = buildtree.BuildTree(with_groups=with_groups, root=document)
-
- def __call__(self,thing):
- """Produce a DOCUTILS 'document' node and attach our information to it
- """
- self.dps.start("document")
-
- if thing.__class__ == visit.Package:
- self.add_package(thing)
- elif thing.__class__ == visit.Module:
- self.add_module(thing)
- else:
- raise ValueError,"Argument must be a Package or Module,"\
- " not a %s"%thing.__class__.__name__
-
- self.dps.end("document")
- document = self.dps.finish()
-
- # David's HTML writer requires the document to have a "source"
- # attribute - so add a temporary one (something better should
- # be done later on - see what David does!)
- document["source"] = "pysource"
- return document
-
- def add_package(self,thing):
- """Process a package and produce DOCUTILS nodes for it.
- """
-
- self.dps.start("section",style="package")
- self.dps.add("target",name=thing.label())
- self.dps.add("title",self.title(thing))
-
- self.dps.start("group",style="details")
- self.dps.add("paragraph","Path: "+thing.directory)
- self.dps.end("group")
-
- for mod in thing.getModules():
- self.add_module(mod)
-
- self.dps.end("section")
-
- def add_module(self,thing):
- """Process a module and produce DOCUTILS nodes for it.
- """
-
- self.current_module = thing
-
- self.dps.add("target",name=thing.label())
- self.dps.start("section",style="module")
- self.dps.add("title",self.title(thing))
-
- self.dps.start("group",style="details")
- self.dps.start("paragraph","Full name: ")
- self.dps.add("emphasis",thing.fullname)
- self.dps.end("paragraph")
- self.dps.add("paragraph","Path: "+thing.filename)
- self.dps.end("group")
-
- self.add_generic(thing)
-
- obscure = thing.getObscureGlobals()
- if obscure:
- self.dps.start("group",style="obscure_globals")
- self.dps.start("paragraph")
- self.dps.add("strong","Globals in obscure places")
- self.dps.start("bullet_list")
-
- for name,places in thing.getObscureGlobals():
- self.dps.start("list_item")
- self.dps.start("paragraph")
- self.dps.add("literal",name)
- self.dps.add("text"," defined and used in")
- if len(places) == 1:
- self.dps.add("text"," ")
- self.dps.add("literal",places[0])
- else:
- self.dps.add("text",":")
- self.dps.start("bullet_list")
- for place in places:
- self.dps.add("list_item",
- self.dps.make("literal",place))
- self.dps.end("bullet_list")
- self.dps.end("list_item")
- self.dps.end("bullet_list")
- self.dps.end("group")
-
- self.dps.end("section")
-
- def add_generic(self,thing):
- """Basic stuff, common to just about all things
- """
-
- # Side effects, all is side effects...
- self.add_docstring(thing)
- self.add_imports(thing)
- self.add_attributes(thing)
- self.add_classes(thing)
- self.add_functions(thing)
-
- def add_docstring(self,thing):
- is_function = (thing.__class__ in [visit.Method,visit.Function])
-
- if not thing.docstring and not is_function:
- return
-
- self.dps.start("group",style="docstring")
-
- if is_function:
- args = thing.getArgs()
- self.dps.start("paragraph")
- # Make the function/method name easily findable...
- self.dps.start("literal",style="funcall")
- self.dps.add("text",thing.name)
- self.dps.end("literal")
- # And then we have the arguments...
- self.dps.add("target",name=thing.args_label())
- self.dps.start("literal",style="funargs")
- self.dps.add("text","(%s)"%string.join(args,", "))
- self.dps.end("literal")
- self.dps.end("paragraph")
-
- if thing.docstring:
- # Insert the docstring into our tree structure
- thing.docstring.add_to_DPS(self.dps)
-
- self.dps.end("group")
-
- # #############################################################
- # Should we sort things alphabetically within each list, below?
- # - maybe yes for some, but no for others...
- # #############################################################
-
- def add_imports(self,thing):
- """Work out a description of any imports.
-
- `thing` is the visitor node that we are to use to construct
- DOCUTILS nodes.
- """
-
- imports = thing.getImports()
- froms = thing.getFromImports()
-
- if not imports and not froms:
- return
-
- self.dps.add("target",name=thing.label())
- self.dps.start("group",style="imports")
- self.dps.start("paragraph")
- self.dps.add("strong","Imports:")
- self.dps.start("bullet_list")
-
- if imports:
- names = imports.keys()
- names.sort()
- for name in names:
- self.dps.start("list_item")
- self.dps.start("paragraph","import ")
- self._add_import(name,imports)
- self.dps.end("list_item")
-
- if froms:
- #print froms
- modnames = froms.keys()
- modnames.sort()
- for modname in modnames:
- self.dps.start("list_item")
- self.dps.start("paragraph","from ")
- self.dps.add("literal",modname)
- self.dps.add("text"," import ")
- dict = froms[modname]
- names = dict.keys()
- names.sort()
- uselist = len(names) > 1
- if uselist:
- self.dps.start("bullet_list")
- for name in names:
- if uselist:
- self.dps.start("list_item")
- self._add_import(name,dict)
- self.dps.end("list_item")
- else:
- self._add_import(name,dict)
- if uselist:
- self.dps.end("bullet_list")
- self.dps.end("list_item")
-
- self.dps.end("bullet_list")
- self.dps.end("group")
-
- def _add_import(self,name,import_dict):
- self.dps.add("literal",name)
- aslist = import_dict[name]
- if len(aslist) == 1 and aslist[0] == None:
- self.dps.add("text"," (as ");
- self.dps.add("emphasis","itself");
- self.dps.add("text",")");
- else:
- self._add_aslist(aslist)
-
- def _add_aslist(self,aslist):
- self.dps.add("text"," as ")
- another = 0
- for name in aslist:
- if another:
- self.dps.add("text",", ")
- else:
- another = 1
- if name is None:
- self.dps.add("emphasis","itself")
- else:
- self.dps.add("literal",name)
-
- def add_attributes(self,thing):
- attributes = thing.getAttributeNames()
- if not attributes:
- return
-
- # We don't do attributes for functions, or for methods that are
- # not called "__init__" or "__new__" (the DOCUTILS spec doesn't require
- # retention of attributes in "__new__" methods, but it seems sensible
- # to me, and I'm not sure they were around when the DOCUTILS spec was
- # first written...)
- if thing.__class__ == visit.Function:
- return
- if thing.__class__ == visit.Method and \
- thing.name not in ("__init__","__new__"):
- return
-
- self.dps.start("group",style="attributes")
- self.dps.start("paragraph")
- self.dps.add("strong","Attributes:")
- self.dps.start("bullet_list")
-
- for name in attributes:
- self.dps.start("list_item")
- nameinst = thing.getAttribute(name)
- self.dps.start("paragraph")
- self.dps.add("target",name=nameinst.label())
- self.dps.add("literal",nameinst.getAsString())
- if nameinst.isGlobal():
- self.dps.add("text"," ")
- self.dps.add("emphasis","(global)")
- if nameinst.__class__ == visit.InstanceValue and \
- nameinst.see_also:
- self.dps.add("text"," - see also class instance ")
- self.dps.add("a",nameinst.our_class.name,
- href="#"+nameinst.our_class.label())
- self.add_docstring(nameinst)
- self.dps.end("list_item")
-
- self.dps.end("bullet_list")
- self.dps.end("group")
-
- def add_classes(self,thing):
- class_names = thing.getClassNames()
- for name in class_names:
- class_instance = thing.getClass(name)
- self.add_class(class_instance)
-
- def add_class(self,thing):
- """Process a class and produce DOCUTILS nodes for it.
- """
-
- self.dps.add("target",name=thing.label())
- self.dps.start("section",style="class")
- self.dps.add("title",self.title(thing))
-
- self.dps.start("group",style="details")
- self.dps.start("paragraph","Full name: ")
- self.dps.add("emphasis",thing.fullname)
-
- names = thing.getBaseNames()
- if names:
- self.dps.start("paragraph","Inherits from: ")
- done_one = 0
- for name in names:
- if done_one:
- self.dps.add("text",", ")
- else:
- done_one = 1
- self.dps.add("literal",name)
- self.dps.end("group")
-
- self.add_generic(thing)
- self.dps.end("section")
-
- def add_functions(self,thing):
- """Add information about any functions or methods.
- """
-
- func_names = thing.getFunctionNames()
- for name in func_names:
- fun_instance = thing.getFunction(name)
- self.add_function(fun_instance)
-
- def add_function(self,thing):
- """Process a function or method and produce DOCUTILS nodes for it.
- """
-
- if thing.__class__ == visit.Method:
- style = "method"
- else:
- style = "function"
- self.dps.add("target",name=thing.label())
- self.dps.start("section",style=style)
- self.dps.add("title",self.title(thing))
-
- self.dps.start("group",style="details")
- self.dps.start("paragraph","Full name: ")
- self.dps.add("emphasis",thing.fullname)
- self.dps.end("group")
-
- if thing.generator:
- self.dps.start("group",style="generator")
- self.dps.add("paragraph","%s %s is actually a generator"%\
- (thing.__class__.__name__,thing.name))
- self.dps.end("group")
-
- self.add_generic(thing)
- self.dps.end("section")
-
- def title(self,thing):
- return "%s %s"%(thing.__class__.__name__,thing.name)
diff --git a/sandbox/tibs/pysource/utils.py b/sandbox/tibs/pysource/utils.py
deleted file mode 100755
index 8823c9265..000000000
--- a/sandbox/tibs/pysource/utils.py
+++ /dev/null
@@ -1,474 +0,0 @@
-"""Utilities for pysource
-"""
-
-import types
-import string
-import compiler
-
-# We'd better have at least *one* module in this package that demonstrates
-# *not* using reST for our docstrings...
-__docformat__ = "none"
-
-
-# ----------------------------------------------------------------------
-PLAINTEXT = "plaintext"
-RESTRUCTUREDTEXT = "restructuredtext"
-
-canonical_format = { "plaintext" : PLAINTEXT,
- "plain" : PLAINTEXT,
- "none" : PLAINTEXT,
- "rst" : RESTRUCTUREDTEXT,
- "rest" : RESTRUCTUREDTEXT,
- "rtxt" : RESTRUCTUREDTEXT,
- "restructuredtext" : RESTRUCTUREDTEXT,
- }
-
-def docformat(text):
- """Interpret a module's __docformat__ string.
-
- Returns a tuple of (format,language)
- """
- if text == None:
- return PLAINTEXT,"en"
-
- words = string.split(string.lower(text))
-
- #print words
-
- if len(words) == 0:
- return PLAINTEXT,"en"
- elif len(words) > 2:
- raise ValueError,"__docformat__ may be at most two 'words'"
-
- if len(words) == 2:
- language = string.lower(words[1])
- else:
- language = "en"
-
- try:
- format = canonical_format[string.lower(words[0])]
- except KeyError:
- legal = canonical_format.keys()
- legal.sort()
- raise ValueError,"__docformat__ should be one of %s"%legal
-
- return format,language
-
-
-# ----------------------------------------------------------------------
-def flatten(item):
- """Retrieve some simpler representation of our AST.
-
- (and it's not meant to be 'theoretically' wonderful, just something
- I can look at to work out how an AST works...)
- """
- if isinstance(item,compiler.ast.Node):
- things = [item.__class__.__name__]
- children = item.getChildren()
- for child in children:
- things.append(flatten(child))
- return things
- else:
- return [item]
-
-
-# ----------------------------------------------------------------------
-def treeprint(stream,item,indent=0):
- """Simple pretty printer for the AST."""
- if isinstance(item,compiler.ast.Node):
- stream.write("\n%s<%s>"%(" "*indent,item.__class__.__name__))
-
- children = item.getChildren()
- for child in children:
- treeprint(stream,child,indent+2)
-
- # Fake our docstring as a sub-node (it's *really* more an attribute)
- if hasattr(item,"docstring"):
- stream.write("\n%s <docstring> %s"%(" "*indent,item.docstring))
-
- # And ditto for a remembered assignment expression
- if hasattr(item,"assign_expr"):
- stream.write("\n%s <assign_expr>"%(" "*indent))
- treeprint(stream,item.assign_expr,indent+4)
- else:
- stream.write(" ")
- stream.write(`item`)
-
-
-# ----------------------------------------------------------------------
-def find_attr_docs(tree,verbose=0):
- """Find candidates for documented attributes
-
- Note that after this, it may be that the AST will not garbage collect
- its own nodes properly anymore, as we are adding in cross-linkages.
- """
-
- if not isinstance(tree,compiler.ast.Node):
- return
-
- children = tree.getChildren()
-
- # Might as well get our recursion done with first...
- for child in children:
- find_attr_docs(child,verbose)
-
- # I believe that only Stmt nodes can have Assign and Discard
- # nodes as children
- if not isinstance(tree,compiler.ast.Stmt):
- return
-
- if len(children) == 0:
- return
-
- pairs = []
- last = children[0]
- for item in children[1:]:
- pairs.append((last,item))
- last = item
-
- for this,next in pairs:
- if isinstance(this,compiler.ast.Assign) and \
- isinstance(next,compiler.ast.Discard):
- if verbose:
- print
- print
- print "*** Attribute docstring candidate"
- treeprint(this,4)
- treeprint(next,4)
- print
-
- nextexpr = next.expr
- if isinstance(nextexpr,compiler.ast.Const):
- if type(nextexpr.value) == types.StringType:
- docstring = nextexpr.value
- else:
- if verbose:
- print
- print "... Discarded constant is not a string"
- continue
- else:
- if verbose:
- print
- print "... Discarded expression is not a constant"
- continue
-
- # If there is more than one assignment attached to
- # the <Assign> node, we are not interested
- if len(this.nodes) > 1:
- if verbose:
- print
- print "... (but there are too many assignments in the <Assign>)"
- continue
-
- target = this.nodes[0]
- if isinstance(target,compiler.ast.AssName):
- # Let's be cheeky and glue the docstring on...
- target.docstring = docstring
- elif isinstance(target,compiler.ast.AssAttr):
- # Let's be cheeky and glue the docstring on...
- target.docstring = docstring
- else:
- if verbose:
- print
- print "... (but the assignment is to a tuple/list/etc.)"
- continue
-
- if verbose:
- print
- print "Becomes:"
- treeprint(this,4)
-
-
-# ----------------------------------------------------------------------
-def find_attr_vals(tree,verbose=0):
- """Find attributes whose values we're interested in.
-
- Clearly, when this is working, it could do with being "folded" into
- `find_attr_docs()`.
-
- Note that after this, it may be that the AST will not garbage collect
- its own nodes properly anymore, as we are adding in cross-linkages.
- """
-
- if not isinstance(tree,compiler.ast.Node):
- return
-
- children = tree.getChildren()
-
- # Might as well get our recursion done with first...
- for child in children:
- find_attr_vals(child,verbose)
-
- # I believe that only Stmt nodes can have Assign and Discard
- # nodes as children
- if not isinstance(tree,compiler.ast.Stmt):
- return
-
- for this in children:
- if isinstance(this,compiler.ast.Assign):
- if verbose:
- print
- print
- print "*** Assignment - name/value candidate"
- treeprint(this,4)
- print
-
- # If there is more than one assignment attached to
- # the <Assign> node, we are not interested
- if len(this.nodes) > 1:
- if verbose:
- print
- print "... (but there are too many assignments in the <Assign>)"
- continue
-
- target = this.nodes[0]
- if isinstance(target,compiler.ast.AssName) or \
- isinstance(target,compiler.ast.AssAttr):
- # Let's be cheeky and glue the associated expression on...
- target.assign_expr = this.expr
- else:
- if verbose:
- print
- print "... (but the assignment is to a tuple/list/etc.)"
- continue
-
- if verbose:
- print
- print "Becomes:"
- treeprint(this,4)
-
-
-# ----------------------------------------------------------------------
-def stringify_arg(thing):
- """Return a string representation of a function argument.
-
- This just works for tuples of (strings or tuples (of strings ...) ...)
- """
- if type(thing) == types.StringType:
- return thing
- elif type(thing) == types.TupleType:
- innards = []
- for item in thing:
- innards.append(stringify_arg(item))
- return "(" + string.join(innards,",") + ")"
- else:
- raise ValueError,"Tried to stringify type %s"%type(thing)
-
-
-# ----------------------------------------------------------------------
-def merge_args(args,defaults):
- """Merge together arguments and defaults from an argument list.
-
- Returns a list of argument strings.
- """
- if args == None:
- return []
-
- if defaults == None:
- defaults = []
-
- # This is horrible - do it nicely later on!
- argstrs = []
- for item in args:
- argstrs.append(stringify_arg(item))
-
- pos = len(args) - len(defaults)
- next = 0
- for index in range(pos,len(args)):
- thing = defaults[next]
- thing = stringify_expr(thing)
- argstrs[index] = "%s=%s"%(argstrs[index],thing)
- next = next + 1
- return argstrs
-
-
-# ----------------------------------------------------------------------
-def stringify_expr(thing):
- """Return a very simple string representation of an expression node
-
- Specifically, this function aims to support stringifying things
- which can be on the RHS of an assignment - is that *actually* the
- same as stringifying expression nodes?
- """
-
- # Humph - saving typing may be a good thing...
- strify = stringify_expr
-
- #print thing.__class__.__name__
-
- if thing == None:
- return 'None'
- elif isinstance(thing,compiler.ast.Add):
- return strify(thing.left) + " + " + strify(thing.right)
- elif isinstance(thing,compiler.ast.And):
- exprs = []
- for node in thing.nodes:
- exprs.append(strify(node))
- return string.join(exprs," && ")
- elif isinstance(thing,compiler.ast.AssAttr):
- # Attribute as target of assignment
- if thing.flags == compiler.consts.OP_ASSIGN:
- return strify(thing.expr) + "." + thing.attrname
- else:
- raise ValueError,"Unexpected flag %d in %s"%(thing.flags,`thing`)
- elif isinstance(thing,compiler.ast.AssName):
- # Name as target of assignment, but this also means name
- # as target of "in" assignment (e.g., "x in [1,2,3]"),
- # which is why *we're* interested in it (since this can
- # occur in list comprehensions, which can occur as the
- # RHS of assignments)
- if thing.flags == compiler.consts.OP_ASSIGN:
- return thing.name
- else:
- raise ValueError,"Unexpected flag %d in %s"%(thing.flags,`thing`)
- elif isinstance(thing,compiler.ast.Backquote):
- return "`" + strify(thing.expr) + "`"
- elif isinstance(thing,compiler.ast.Bitand):
- exprs = []
- for node in thing.nodes:
- exprs.append(strify(node))
- return string.join(exprs," & ")
- elif isinstance(thing,compiler.ast.Bitor):
- exprs = []
- for node in thing.nodes:
- exprs.append(strify(node))
- return string.join(exprs," | ")
- elif isinstance(thing,compiler.ast.Bitxor):
- exprs = []
- for node in thing.nodes:
- exprs.append(strify(node))
- return string.join(exprs," ^ ")
- elif isinstance(thing,compiler.ast.CallFunc):
- # Yuck - this is getting complicated!
- # (for an example, see method `hyperlink_target` in
- # restructuredtext/states.py)
- str = strify(thing.node) + "("
- arglist = []
- if thing.args:
- for arg in thing.args:
- arglist.append(strify(arg))
- if thing.star_args:
- arglist.append("*"+strify(thing.star_args))
- if thing.dstar_args:
- arglist.append("**"+strify(thing.dstar_args))
- if arglist:
- str += string.join(arglist,", ")
- return str+")"
- elif isinstance(thing,compiler.ast.Compare):
- str = strify(thing.expr) + " "
- for op,val in thing.ops:
- str += op + " " + strify(val)
- return str
- elif isinstance(thing,compiler.ast.Const):
- # Try not to let long strings take up too much room...
- value = thing.value
- if type(value) == type("") and len(value) > 50:
- value = value[:47] + "..."
- # Make Python decide for us if it needs quotes round it
- # (and, if so, what sort)
- return `value`
- elif isinstance(thing,compiler.ast.Dict):
- innards = []
- for key,val in thing.items:
- key = strify(key)
- val = strify(val)
- innards.append(key+":"+val)
- return "{" + string.join(innards,", ") + "}"
- elif isinstance(thing,compiler.ast.Div):
- return strify(thing.left) + " / " + strify(thing.right)
- elif isinstance(thing,compiler.ast.Ellipsis):
- return "..."
- elif isinstance(thing,compiler.ast.Getattr):
- return strify(thing.expr) + "." + thing.attrname
- elif isinstance(thing,compiler.ast.Invert):
- # Bitwise negation
- return "~" + strify(thing.expr)
- elif isinstance(thing,compiler.ast.Keyword):
- # An 'arg=value' within a function call
- return thing.name + "=" + strify(thing.expr)
- elif isinstance(thing,compiler.ast.Lambda):
- str = "lambda "
- if thing.flags != 0:
- str += " <flag %d> "%thing.flags
- str += string.join(merge_args(thing.argnames,thing.defaults),", ")
- str += ": "
- str += strify(thing.code)
- return str
- elif isinstance(thing,compiler.ast.LeftShift):
- return strify(thing.left) + " << " + strify(thing.right)
- elif isinstance(thing,compiler.ast.List):
- innards = []
- for item in thing.nodes:
- innards.append(strify(item))
- return "[" + string.join(innards,", ") + "]"
- elif isinstance(thing,compiler.ast.ListComp):
- str = "["+strify(thing.expr)
- for node in thing.quals:
- str += " "+strify(node)
- return str+"]"
- elif isinstance(thing,compiler.ast.ListCompFor):
- str = "for "+strify(thing.assign)
- str += " in "+strify(thing.list)
- if thing.ifs:
- for node in thing.ifs:
- str += " "+strify(node)
- return str
- elif isinstance(thing,compiler.ast.ListCompIf):
- return "if "+strify(thing.test)
- elif isinstance(thing,compiler.ast.Mod):
- return strify(thing.left) + "%" + strify(thing.right)
- elif isinstance(thing,compiler.ast.Mul):
- return strify(thing.left) + " * " + strify(thing.right)
- elif isinstance(thing,compiler.ast.Name):
- return thing.name
- elif isinstance(thing,compiler.ast.Not):
- return "not " + strify(thing.expr)
- elif isinstance(thing,compiler.ast.Or):
- exprs = []
- for node in thing.nodes:
- exprs.append(strify(node))
- return string.join(exprs," || ")
- elif isinstance(thing,compiler.ast.Power):
- return strify(thing.left) + " ** " + strify(thing.right)
- elif isinstance(thing,compiler.ast.RightShift):
- return strify(thing.left) + " >> " + strify(thing.right)
- elif isinstance(thing,compiler.ast.Slice):
- if thing.flags != compiler.consts.OP_APPLY:
- raise ValueError,"Unexpected flag %d in %s"%(thing.flags,`thing`)
- return strify(thing.expr) + "[" + \
- strify(thing.lower) + ":" + strify(thing.upper) + "]"
- elif isinstance(thing,compiler.ast.Sliceobj):
- slicelist = []
- for idx in thing.nodes:
- slicelist.append(strify(idx))
- return string.join(slicelist,":")
- elif isinstance(thing,compiler.ast.Sub):
- return strify(thing.left) + " - " + strify(thing.right)
- elif isinstance(thing,compiler.ast.Subscript):
- if thing.flags != compiler.consts.OP_APPLY:
- raise ValueError,"Unexpected flag %d in %s"%(thing.flags,`thing`)
- str = strify(thing.expr) + "["
- sublist = []
- for sub in thing.subs:
- sublist.append(strify(sub))
- return str + string.join(sublist,", ") + "]"
- elif isinstance(thing,compiler.ast.Tuple):
- innards = []
- for item in thing.nodes:
- innards.append(strify(item))
- return "(" + string.join(innards,", ") + ")"
- elif isinstance(thing,compiler.ast.UnaryAdd):
- return "+" + strify(thing.expr)
- elif isinstance(thing,compiler.ast.UnarySub):
- return "-" + strify(thing.expr)
- else:
- return _whatsthis(thing)
-
-def _whatsthis(thing):
- # Wrong, but what else can we do?
- import sys
- print >>sys.stderr,"stringify_expr - don't recognise %s %s"%\
- (thing.__class__.__name__,thing)
- return `thing`
-
-
diff --git a/sandbox/tibs/pysource/visit.py b/sandbox/tibs/pysource/visit.py
deleted file mode 100755
index ec5a2992f..000000000
--- a/sandbox/tibs/pysource/visit.py
+++ /dev/null
@@ -1,2074 +0,0 @@
-#! /usr/bin/env python
-"""Extract information from a Python file (module) for the DOCUTILS
-
-An example of using Jeremy Hylton's compiler module.
-
-Originally based on an example *by* Jeremy Hylton. In the introduction
-to that example, he said:
-
- Here's a trivial example program that extracts some information
- about methods and attributes from a class and its methods.
- I wasn't exhaustive here. I'll get attributes assigned to by
- `self.x` in a method body and I'll get method definitions in
- the class body. I don't deal with obvious things like attributes
- defined at the class level.
-
-I'm expanding it, initially as a bigger example, and also so I get to
-understand how things work!
-
-Note: there should be an example Python file called test.py in the
-same directory as this module - it's meant to be a suitable input
-for testing/learning purposes.
-
-:Author: Tibs <tibs@tibsnjoan.co.uk>
-:Version: Whatever. Oh, 0.4, then
-:Date: 2002-January-18
-
-Aims for DOCUTILS
------------------
-1. Locate all modules, classes, functions, methods and their docstrings.
-2. "Filter" these to leave the ones that DOCUTILS is interested in.
-3. Annotate functions and methods with their arguments.
-4. Locate all assignments which have docstrings.
-5. Similarly "filter" these.
-6. Locate all uses of `global` assignments.
-7. Filter out those which are not obvious from the module level,
- so that the user can be warned about them.
-8. Produce a tree structure suitable for DOCUTILS processing, containing
- the suitable results of the above.
-
-(At least some of) 1, 3 and 4 have already been done.
-
-Still to do
------------
-* *all* sorts of assignment should be visited, so that
- we can tie down the use of globals properly.
-* the option of ignoring _name and __name things should be
- available (should this be the default?)
-* Some consideration should be given to freeing up this mess of things
- when they are all finished with - there are so many interconnections
- that automatic deletion is unlikely to work well
-* other things as they occur to me
-* Finish off InstanceValue (its potential link to the class that defines it)
-
-Names and fullnames
--------------------
-A "name" is taken to be the name as presented in Python code. Note that
-for class instance attribute references (e.g., "self.fred"), the name is
-includes the class reference, dot and attribute name (e.g., "self.fred").
-
-A "fullname" includes the full path to the name as well - that is,
-including all of the elements required to "reach" this item. Thus, for
-instance, a method Fred in class Jim in module Bill would be::
-
- Bill.Jim.Fred
-
-whilst a name A defined within Fred would be::
-
- Bill.Jim.Fred:A
-
-Note that if Fred contains a reference to self.B, then that would (for the
-moment at least) be written as::
-
- Bill.Jim.Fred:self.B
-
-Within an eventual HTML document, such fullnames become anchor and link
-names for nodes. For that purpose, they will be transformed so that they
-do not contain "." or ":", but are still not accidentally confusable with
-legitimate Python names. Thus the last example would be transformed to::
-
- Bill-Jim-Fred--self-B
-
-Note that we also have a "special" label, artificially "generated" - that
-is, there is a single label for all arguments to a function or method,
-which is formed of the label for the function or method, followed by
-*three* hyphens, and then the text "args" - so, for example:
-
- Bill-Jim---args
-
-Special cases
--------------
-Notes on special cases in name resolution:
-
-- obviously I should be taking account of explicit roles.
-
-- if it can't find the name directly via the "scope", it should be looking
- up in the module - so the ScopeMixin needs to provide support for that...
-
-- the module name should be recognised as, in some sense, within the
- module's "parent" - even if there is no such beast.
-
-- that generalises - in general, an object's own name should be visible
- to its docstring, I think - so, for instance::
-
- digit = 3
- '''We store the current digit of pi in `digit`'''
-
- (yes, I know that's poor documentation, but even so)
-
-- <self>.name in a method (where <self> is the first argument to said
- method) should be regarded as being a name in the class containing
- the method, in some sense (but what sense?)
-""" #"
-
-import os
-import sys
-import string
-import compiler
-
-from docutils.parsers.rst import Parser
-
-# Local modules
-import utils
-import visit
-
-__docformat__ = "reST"
-
-
-# ----------------------------------------------------------------------
-def make_Docstring(text, settings):
- """A factory function to handle non-existant docstrings.
- """
- if text:
- return Docstring(text, settings)
- else:
- return None
-
-class Docstring:
- """We use this to represent a docstring, parsed and unparsed.
- """
-
- def __init__(self, text, settings, debug=0):
- """Instantiate a new Docstring from its text.
- """
- self.text = self._trim(text)
- """The text of the docstring.
- """
- self.document = None
- """The result of parsing the docstring, if requested.
- (thus, only non-None if we *are* parsing docstrings in
- the containing module).
- """
- self.settings = settings
- """The docutils settings to apply to new document parsers.
- """
-
- self.debug = debug
-
- def _trim(self,docstring):
- """Trim leading space appropriately from the docstring text.
-
- When the docstring is read from the source file, it is likely
- to have all but the first line indented with respect to the
- first - for example, consider this docstring.
-
- Before it is *used* for anything (e.g., typing it out to be
- read by the user), it is necessary to adjust for this. The
- way to do this is well-defined (???where???).
-
- Returns the adjusted text.
- """
-
- # Remove any confusing tabs - follow the normal Python rules
- # - and split into convenient lines
- lines = string.split(string.expandtabs(docstring),"\n")
-
- # Find significant indentation
- firstline = lines[0]
- if firstline and firstline[0] == " ":
- oldlen = len(firstline)
- firstline = string.lstrip(firstline)
- indent = oldlen - len(firstline)
- else:
- indent = 0
- for line in lines[1:]:
- oldlen = len(line)
- lin = string.lstrip(line)
- if lin:
- indent = oldlen - len(lin)
- break
-
- # And remove it...
- newlines = [firstline]
- for line in lines[1:]:
- oldlen = len(line)
- lin = string.lstrip(line)
- if lin:
- extra = oldlen - len(lin) - indent
- if extra > 0:
- lin = " "*extra + lin
- newlines.append(lin)
-
- # Don't introduce a trailing blank line if they did some
- # variant of the following layout::
- # """Some text
- # """
- if newlines and newlines[-1] == "":
- del newlines[-1]
-
- # And lastly, reassemble it back into text again
- return string.join(newlines,"\n")
-
- def show(self,stream,spaces=""):
- # Not optimised for efficiency...
- lines = string.split(self.text,"\n")
-
- # For the moment, don't try to format it very nicely at all...
- stream.write('%s"""%s\n'%(spaces,lines[0]))
- for line in lines[1:]:
- stream.write(spaces+line+"\n")
- stream.write('%s"""\n'%spaces)
-
- def parse(self,parser):
- """Parse our text with the given parser.
- """
- import docutils
- self.document = docutils.utils.new_document(self.text, self.settings)
- parser.parse(self.text,self.document)
-
- def add_to_DPS(self,dps):
- """Add this docstring content to a DOCUTILS subtree.
-
- Calls the appropriate things from `dps`, which is a
- builtree.BuildTree instance.
- """
- if self.document:
- for child in self.document.children:
- dps.addsubtree(child)
- else:
- dps.start("literal_block")
- dps.add("text",self.text)
- dps.end("literal_block")
-
- # ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
- # Experimental <interpreted> node code...
- # Copied from transform.py, and not adjusted yet (except superficially
- # and stupidly) for its position in this class.
- # - despite the comments in the docstring, it doesn't *do* anything yet...
-
- def transform_interpreted(self,thing):
- """Deal with <interpreted> nodes in this docstring.
-
- The intent is to find any <interpreted> nodes, try to locate the
- relevant Python value, and insert an appropriate cross-reference.
-
- `thing` is the `Module`, `Class`, `Function`, `Method` or
- `Name` instance to which this docstring is "attached". It
- is used to resolve the <interpreted> names.
- """
- if self.debug:
- print "\n*** Locating <interpreted> items for %s"%thing.fullname
- self.show(sys.stdout," ")
- self.locate_interpreted(self.document,thing)
-
- def locate_interpreted(self,element,thing):
- """Deal with finding "interpreted" nodes in a document subtree.
- """
- for node in element:
- if node.tagname == "#text":
- continue
- elif node.tagname == "interpreted":
- self.treat_interpreted(node,thing)
- else:
- self.locate_interpreted(node,thing)
-
- def treat_interpreted(self,element,thing):
- """Do something interesting with an "interpreted" node.
- """
- if element.has_key("role"):
- role = element["role"]
- else:
- role = None
-
- name = element.astext()
-
- #if role:
- # print "...<interpreted> :%s: %s"%(role,name)
- #else:
- # print "...<interpreted> %s"%name
-
- # Attempt to work out what this <interpreted> item refers to
- target = thing.scope_find_name(name,role=role,indent="...")
- if target:
- element["refname"] = target
-
-
-# ----------------------------------------------------------------------
-class ScopeMixin:
- """Learning about how to represent scope.
-
- The idea of this mixin class is to work out the best way of representing
- scope, so that I can use the results when working out exactly what an
- <interpreted> item in a docstring refers to.
-
- Note that I do not intend (at least, for the moment) to worry about Python
- before 2.2 - i.e., before embedded scope became non-optional. This is
- purely laziness on my part...
- """
-
- scope_debug = 0
-
- def scope_init(self):
- """Call at the end of `__init__` to initilise our experiments
- """
-
- self.scope_module = None
- """Which Module we are in.
- """
-
- self.scope_parent = None
- """The *immediate* parent entity.
- Note that for a method, this will be the class defining it.
-
- (Ultimately, it might be better if this were a weak reference.)
- """
-
- self.scope_encloser = None
- """The innermost enclosing block. Note that for a method,
- this should *not* be the class, but the innermost enclosing
- function/method/module/whatever (whatever?).
- """
-
- self.scope_defines = []
- """A list of the names *defined* by this entity
- (by assignment, definition or whatever).
-
- The list is ordered by last occurrence of the name.
- """
-
- self.scope_fullname = {}
- """The key is the name from `self.scope_defines`, the value is the
- "full" name for the defined value.
- """
-
- self.scope_children = {}
- """A dictionary of the entities defined by this entity.
-
- The keys are the entity name (so correspond to those in
- `self.scope_defines`), and the values are NULL if the entity
- is defined by simple assignment, otherwise the relevant
- "scope" instance (e.g., a Method or Class).
- """
-
- self.scope_globals = []
- """A list of names which are declared global in this scope.
- """
-
- def scope_define_parent(self,parent=None,module=None):
- """Define our parent and encloser.
- """
- self.scope_module = module
- self.scope_parent = parent
- self.scope_encloser = parent
- if isinstance(self,Method):
- while isinstance(self.scope_encloser,Class):
- self.scope_encloser = self.scope_encloser.scope_parent
-
- def scope_define_name(self,name,fullname,child=None):
- """Add a name that is defined in this scope.
-
- - `name` is the obvious name of the name being defined.
- - `fullname` is the "path" to it, starting at the module.
- - `child` is the class representing that name - e.g., a Class
- or Name instance.
-
- Note - remember that functions/methods "define" their arguments...
-
- HOWEVER we are not trying for a general solution to the problem of
- "find the item that is being referred to" - we are just trying to
- provide useful links between <interpreted> items in docstrings and
- those things that they might reasonably be expected to be referring to.
-
- Furthermore, we know that we will not show attributes, docstring or
- not, if they are not
-
- a. At module level (so a ModuleValue)
- b. Within a class (so a ClassValue)
- c. Within a method called __init__ or __new__.
- d. An argument (we always want to know about arguments).
-
- So we discard any attributes that do not match these criteria...
- """
- if self.scope_debug:
- if name in self.scope_defines:
- redef = "(re)"
- else:
- redef = " "
- print "%-15s %-30s %sdefined in %s"%(child.__class__.__name__,
- name,redef,self.name)
-
- # Should we ignore this name?
- if isinstance(child,Name):
- if self.__class__ not in [Package,Module,Class] and \
- not (self.__class__ == Method and
- self.name in ["__init__","__new__"]) and \
- child.__class__ != Argument:
- return
- # Remember to ensure the name is always at the END of the list
- # (even if it was already there)
- if name in self.scope_defines:
- self.scope_defines.remove(name)
- self.scope_defines.append(name)
- self.scope_fullname[name] = fullname
- self.scope_children[name] = child
-
- def scope_define_global(self,name):
- """Indicate that a name is actually global.
-
- Note that it is entirely possible that the name is also present
- in `self.scope_defines` - being global should be remembered as taking
- precedence.
- """
- if self.scope_debug:
- if name in self.scope_defines:
- redef = "(re)"
- else:
- redef = " "
- print "%-10s %-30s %sdefined in %s"%("[Global]",
- name,redef,self.name)
- if name not in self.scope_globals:
- self.scope_globals.append(name)
-
- def scope_get_object(self,name):
- """Return the defined object corresponding to `name`, or None.
- """
- try:
- return self.scope_children[name]
- except:
- return None
-
- def scope_get_type(self,name):
- """Return the "type" of the defined object corresponding to `name`.
- """
- try:
- return self.scope_children[name].__class__.__name__
- except:
- return None
-
- def scope_name_in_self(self,name):
- """Return true if the `name` is defined by ourselves.
- """
- return name in self.scope_defines
-
- def scope_name_in_encloser(self,name):
- """Return true if the `name` is defined by our encloser.
-
- (If we don't *have* an encloser - e.g., we're a module - then
- it obviously returns false.)
- """
- if self.scope_encloser:
- return name in self.scope_encloser.scope_defines
- else:
- return 0
-
- def scope_name_in_module(self,name):
- """Return true if the `name` is defined by our module.
- """
- if self.scope_module:
- return name in self.scope_module.scope_defines
- else:
- return 0
-
- def scope_up_is_module(self):
- """Is our encloser the module?
- """
- return self.scope_module == self.scope_encloser
-
- # We need a dictionary to relate role names to the classes we use
- # A value of None against a key means that we are not attempting
- # to handle this yet.
- roles = {"package" : "Package",
- "module" : "Module",
- "class" : "Class",
- "method" : "Method",
- "function" : "Function",
- "module_attribute" : "ModuleValue",
- "class_attribute" : "ClassValue",
- "instance_attribute": "InstanceValue",
- "variable" : "Name",
- "parameter" : "Argument",
- "type" : None,
- "exception_class" : None,
- "exception" : None,
- "warning_class" : None,
- "warning" : None}
-
- def scope_obj_role_match(self,what,role):
- """Decide if the role (if any) makes sense with respect to `what`.
-
- `what` is the object we thing might be our item of interest,
- and `role` is the role we're looking for, or None if we're not
- particular.
- """
- if role:
- if what.__class__.__name__ == self.roles[role]:
- return 1
- else:
- return 0
- else:
- return 1
-
- def scope_class_role_match(self,class_name,role):
- """Decide if the role (if any) makes sense with respect to `what`.
-
- `what` is the class name of the object we thing might be our item
- of interest, and `role` is the role we're looking for, or None if
- we're not particular.
- """
- if role:
- if class_name == self.roles[role]:
- return 1
- else:
- return 0
- else:
- return 1
-
- def scope_callable_match(self,what,need_callable):
- """Does the callable state of the `what` match our needs? Do we care?
- """
- if need_callable:
- return what.is_callable()
- else:
- return 1
-
- def scope_find_name(self,name,role=None,indent=" "):
- """A first pass at looking up names in scope.
-
- - `name` is the text that the user has enclosed in backquotes,
- to make it interpreted
- - `role`, if given, specifies exactly what sort of name the
- user determines it to be.
-
- This makes no attempt to do anything beyond looking up a
- simple name - it doesn't try to deal with (for instance)
- a "()" at the end of the name, nor does it try to cope
- with dotted names in any clever way.
-
- Returns either the label for the referenced entity (which is
- a translation of its `fullname` into something legal as an
- XML name), or None.
- """
- if name.endswith("()"):
- name = name[:-2]
- need_callable = 1
- else:
- need_callable = 0
-
- if self.scope_debug:
- print indent,
- if role:
- print ":%s:"%role,
-
- # Is it a reference to ourself?
- if name == self.name and \
- self.scope_obj_role_match(self,role) and \
- self.scope_callable_match(self,need_callable):
- if self.scope_debug:
- print "%s '%s' IS %s %s"%\
- (self.__class__.__name__,name,
- self.__class__.__name__,self.name)
- return self.label()
-
- # Is it a reference to one of our children?
- if self.scope_name_in_self(name):
- what = self.scope_get_type(name)
- whom = self.scope_children[name]
- if self.scope_class_role_match(what,role) and \
- self.scope_callable_match(whom,need_callable):
- if self.scope_debug:
- print "%s '%s' found HERE in %s %s"%\
- (what,name,self.__class__.__name__,self.name)
- if whom.__class__ == Argument:
- return self.args_label()
- else:
- return whom.label()
-
- # Is it a reference to one of our encloser's children?
- if self.scope_name_in_encloser(name):
- what = self.scope_encloser.scope_get_type(name)
- whom = self.scope_encloser.scope_children[name]
- if self.scope_class_role_match(what,role) and \
- self.scope_callable_match(whom,need_callable):
- if self.scope_debug:
- print "%s '%s' found UP in %s %s"%\
- (what,name,self.scope_encloser.__class__.__name__,
- self.scope_encloser.name)
- if whom.__class__ == Argument:
- return self.scope_encloser.args_label()
- else:
- return whom.label()
-
- # Is it a reference to our encloser?
- if self.scope_encloser and name == self.scope_encloser.name:
- # I'm not sure about this one - *should* we be able to "see"
- # the name of our encloser? Or is what I'm *really* after
- # the name of the *parent*?
- #
- # Specific instance - consider a method M in class C
- # - should `C` in `M`s docstring refer to class C,
- # even if class C is *not* defined at module level?
- if self.scope_obj_role_match(self.scope_encloser,role) and \
- self.scope_callable_match(self.scope_encloser,need_callable):
- if self.scope_debug:
- print "%s '%s' IS %s %s"%\
- (self.scope_encloser.__class__.__name__,name,
- self.scope_encloser.__class__.__name__,
- self.scope_encloser.name)
- return self.scope_encloser.label()
-
- # Is it a reference to a child of our module?
- if not self.scope_up_is_module() and self.scope_name_in_module(name):
- what = self.scope_module.scope_get_type(name)
- whom = self.scope_module.scope_children[name]
- if self.scope_class_role_match(what,role) and \
- self.scope_callable_match(whom,need_callable):
- if self.scope_debug:
- print "%s '%s' found GLOBAL in %s %s"%\
- (what,name,self.scope_module.__class__.__name__,
- self.scope_module.name)
- # Modules don't have arguments...
- return whom.label()
-
- # Is it a reference to our module itself?
- if name == self.scope_module.name:
- if self.scope_obj_role_match(self.scope_module,role) and \
- not need_callable:
- if self.scope_debug:
- print "%s '%s' IS %s %s"%\
- (self.scope_module.__class__.__name__,name,
- self.scope_module.__class__.__name__,
- self.scope_module.name)
- return self.scope_module.label()
-
- if self.scope_debug:
- print "'%s' not in %s %s"%(name,self.__class__.__name__,self.name),
- if self.scope_encloser:
- print "or %s %s"%(self.scope_encloser.__class__.__name__,
- self.scope_encloser.name),
- if self.scope_up_is_module():
- print
- else:
- print "or %s %s"%(self.scope_module.__class__.__name__,
- self.scope_module.name)
- return None
-
- def scope_show(self,indent=""):
- print "%s%s %s"%(indent,self.__class__.__name__,self.name),
- if self.scope_encloser and self.scope_encloser != self.scope_parent:
- print "<<upscope %s %s>>"%(self.scope_encloser.__class__.__name__,
- self.scope_encloser.name)
- else:
- print
-
- extra_indent = indent+" "
-
- if self.scope_globals:
- print "%sglobals %s"%(extra_indent,self.scope_globals)
-
- for name in self.scope_defines:
- child = self.scope_children[name]
- if child:
- child.scope_show(extra_indent)
-
-
-# ----------------------------------------------------------------------
-class Base(ScopeMixin):
- """A simple base class for common functionality.
- """
-
- verbose = 0
-
- def __init__(self, settings, name, fullname, docstring=None):
- self.settings = settings
- """ The parser settings
- """
-
- self.name = name
- """The name of this scope entity.
- """
-
- self.fullname = fullname
- """The fully qualified name of this entity
- - for instance, for a method `fred` in a class `Jim`
- in a module `bob`, this would be "bob.Jim.fred"
- """
-
- self.docstring = make_Docstring(docstring, settings)
- """The docstring for this scope, or None.
- Note that, at least for the moment, we're only supporting
- one docstring for an entity. This may need to change for
- proper DOCUTILS support (but I [1]_, personally, hope not).
-
- .. [1] "I" being Tibs, at this point, and at this time [2]_.
- .. [2] "This time" being April 2002.
- """
-
- self.imports = {}
- """Import statements within this scope. The key is the
- name of each module being imported, the value is a list
- of the names "as" which the module is imported, with
- `None` meaning "as itself".
- """
-
- self.from_imports = {}
- """From <module> import <names> statements within this
- scope. The key is the <module>, the value a dictionary
- like that used for `self.imports`.
- """
-
- self.classes = {}
- """Classes defined within this scope. The key is the
- class name, the value is the Class instance for this ``class``.
- """
-
- self.functions = {}
- """Functions or methods defined within this scope. The key is the
- function name, the value is the Function or Method instance
- for this ``def``.
- """
-
- self.attributes = {}
- """Attributes assigned to within a scope. The key is the
- attribute name, the value is the Name instance for this ``name``.
- """
-
- self.children = []
- """A list of all of the items contained herein which might
- have, or have children which have, docstrings - i.e., packages,
- modules, classes, functions, methods.
- """
-
- self.class_list = []
- """A list of the class names defined in this scope, in order.
- """
-
- self.function_list = []
- """A list of the function/method names defined in this scope, in order.
- """
-
- self.attribute_list = []
- """A list of the attribute names defined in this scope, in order.
- """
-
- self.globals = {}
- """The names mentioned in global statements within a scope.
- The key is the name, the value doesn't matter.
- """
-
- self.parser = None
- """We may need a reStructuredText parser to handle our docstrings
- - if so, we'll generate one "on demand"."""
-
- def getParser(self):
- """Retrieve a reStructuredText parser, for docstring usage.
- """
- if not self.parser:
- self.parser = Parser()
- return self.parser
-
- def parse_docstrings(self,parser):
- """If we are meant to, parse our docstrings.
- """
- if self.docstring:
- self.docstring.parse(parser)
- for child in self.children:
- child.parse_docstrings(parser)
-
- def is_callable(self):
- """Does it make sense to call an object of this type?
- """
- return 0
-
- def label(self):
- """Return an XML-legal name for this object.
-
- Note that we implicitly assume that all objects have their
- output XML/HTML representation written to the same file
- - i.e., that we do not have to worry about references that
- are anything beyond simple names.
- """
- str = string.replace(self.fullname,".","-")
- str = string.replace(str,":","--")
- return str
-
- def addGlobal(self,name):
- self.globals[name] = name
-
- def addClass(self,klass):
- self.classes[klass.name] = klass
- self.class_list.append(klass.name)
- self.children.append(klass)
-
- def addFunction(self,func):
- self.functions[func.name] = func
- self.function_list.append(func.name)
- self.children.append(func)
-
- def addAttribute(self,name,instance):
- self.attributes[name] = instance
- self.attribute_list.append(name)
- self.children.append(instance)
-
- def addImport(self,names):
- """Remember an import statement.
-
- `names` is a list of ``(name,as)`` tuples, where ``name``
- is the name of the item being imported, and ``as`` is either
- None of else the name "as" which this item is being imported
-
- Note we aren't even *trying* to remember its exact locality.
- """
- for name,as in names:
- if not self.imports.has_key(name):
- self.imports[name] = [as]
- else:
- if as not in self.imports[name]:
- self.imports[name].append(as)
-
- def addFromImport(self,modname,names):
- """Remember a from import statement.
-
- `modname` is the name of the module "from" which things are
- being imported.
-
- `names` is a list of ``(name,as)`` tuples, where ``name``
- is the name of the item being imported, and ``as`` is either
- None of else the name "as" which this item is being imported
-
- Note we aren't even *trying* to remember its exact locality.
- """
- if not self.from_imports.has_key(modname):
- self.from_imports[modname] = {}
-
- dict = self.from_imports[modname]
- for name,as in names:
- if not dict.has_key(name):
- dict[name] = [as]
- else:
- if as not in dict[name]:
- dict[name].append(as)
-
- def isGlobal(self,name):
- return self.globals.has_key(name)
-
- def getClassNames(self):
- return self.class_list
- #return self.classes.keys()
-
- def getClass(self,name):
- return self.classes[name]
-
- def getFunctionNames(self):
- return self.function_list
- #return self.functions.keys()
-
- def getFunction(self,name):
- return self.functions[name]
-
- def getAttributeNames(self):
- return self.attribute_list
- #return self.attributes.keys()
-
- def getAttribute(self,name):
- return self.attributes[name]
-
- def getAttributeDocstring(self,name):
- """Return an attribute docstring, or None
- """
- return self.attributes[name]
-
- def getImports(self):
- """Return our "import"s, but not in any particular order.
- """
- return self.imports
-
- def getFromImports(self):
- """Return our "from ... import"s, but not in any particular order.
- """
- return self.from_imports
-
- def getFromImportNames(self,name):
- return self.from_imports[name]
-
- def getSelf(self):
- """Return the name used for "self". Doesn't do much elsewhere.
-
- (Actually, for a method *or* a function, it returns the name
- of the first argument.)
- """
- return None
-
- def _show_body(self,stream,indent=0):
- spaces = indent*" "
-
- if self.docstring:
- self.docstring.show(stream,spaces+" ")
-
- if self.imports:
- names = self.imports.keys()
- stream.write("%s Import %s\n"%(spaces,string.join(names,", ")))
-
- if self.from_imports:
- modnames = self.from_imports.keys()
- for mod in modnames:
- names = self.from_imports[mod]
- stream.write("%s From %s import %s\n"%\
- (spaces,mod,string.join(names,", ")))
-
- # Should we sort things alphabetically within each list?
-
- if self.verbose:
- globals = self.globals.keys()
- if globals:
- stream.write("%s Global statements\n"%spaces)
- for name in globals:
- stream.write("%s %s\n"%(spaces,name))
-
- attributes = self.attributes.keys()
- if attributes:
- stream.write("%s Attributes\n"%spaces)
- for name in attributes:
- self.attributes[name].show(stream,indent+4)
-
- class_names = self.classes.keys()
- if class_names:
- for name in class_names:
- self.classes[name].show(stream,indent+2)
-
- func_names = self.functions.keys()
- if func_names:
- for name in func_names:
- self.functions[name].show(stream,indent+2)
-
- def show(self,stream,indent=0):
- """Override as necessary."""
- stream.write("%s%s %s\n"%(" "*indent,self.__class__.__name__,
- self.name))
- self._show_body(stream,indent)
-
- # ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
- # Experimental <interpreted> node code...
- def find_docstrings(self):
- """Find each docstring in our subtree.
- """
- if self.docstring:
- self.docstring.transform_interpreted(self)
- for child in self.children:
- child.find_docstrings()
- # ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
-
-
-# ----------------------------------------------------------------------
-class Package(Base):
- """The representation of a Python package.
-
- Unlike the other children of `Base`, this class actually visits
- its members itself - that is, it is self-constructing.
- """
-
- def __init__(self,settings,directory,parent=None,debug=0):
- """Instantiate a new package.
-
- If this is a "sub" package, then `parent` should be a Package
- instance, within which we may be found...
-
- `settings` will give the parsing settings -- `verbose_parse` will
- cause the generation of a message for each stage of the production
- of our data, and `debug` will give a message for each "entity"
- in the AST that we visit.
- """
-
- self.settings = settings
- self.verbose = settings.verbose_parse
- self.debug = debug
-
- path = os.path.expanduser(directory) # expand "~"
- path = os.path.expandvars(directory) # expand "$fred" or "%fred%"
- path = os.path.abspath(path) # expand to a 'full' path
- path = os.path.normpath(path) # sort out "/fred" versus "/fred/"
- self.directory = path
- """The `directory` is our best guess as to the actual
- path to the package."""
-
- # Take the package name to be the final component
- base,name = os.path.split(path)
- if parent:
- fullname = parent.fullname + "." + name
- Base.__init__(self,settings,name,fullname)
- else:
- # With no parent, our name and fullname are the same.
- Base.__init__(self,settings,name,name)
-
- self.modules = {}
- """Remember the modules (or Python files, really)
- in this package. The key is the module name, the
- value the Module instance for this module.
- """
-
- # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- # Experimental scope setup
- self.scope_init()
- # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- self.parse_modules()
-
- def parse_modules(self):
- """Locate our constituent modules and parse them.
- """
- files = os.listdir(self.directory)
-
- if "__init__.py" not in files:
- raise ValueError,\
- "Directory %s does not contain an __init__.py file"%\
- self.directory
-
- # Parsing the __init__.py file may give us further information,
- # such as an __all__ value, which we may later want to use to
- # determine which files to read and parse, and which to ignore
- path = os.path.join(self.directory,"__init__.py")
- self.addModule(Module(self.settings,path,package=self, debug=self.debug))
-
- # But, for the moment, just parse all the Python files...
- for file in files:
- name,ext = os.path.splitext(file)
- if name == "__init__":
- continue
- elif ext in [".py",".pyw"]:
- path = os.path.join(self.directory,file)
- self.addModule(Module(self.settings,path,package=self,
- debug=self.debug))
-
- def addModule(self,mod):
- self.modules[mod.name] = mod
- self.children.append(mod)
-
- def getModuleNames(self):
- return self.modules.keys()
-
- def getModule(self,name):
- return self.modules[name]
-
- def getModules(self):
- """Return a list of Module instances.
- """
- return self.modules.values()
-
- def show(self,stream,indent=0):
- stream.write("%sPackage %s"%(" "*indent,self.name))
- if self.directory:
- stream.write("(in %s)\n"%self.directory)
- else:
- stream.write("\n")
-
- names = self.modules.keys()
- names.sort()
- for name in names:
- self.modules[name].show(stream)
-
- def show_ast(self,stream):
- """Print out a representation of our ASTs.
- """
- names = self.modules.keys()
- names.sort()
- for name in names:
- self.modules[name].show_ast(stream)
-
-
-# ----------------------------------------------------------------------
-class Module(Base):
- """The representation of a Python module.
-
- This class also knows how to *parse* a Python module.
-
- Still known to be missing:
-
- - visitLambda (I shudder)
- - should we also do visitExec?
-
- - visitAssign
- - visitAugAssign
-
- These last two are needed to allow us to link a Name with its value(s).
-
- If attribute docstrings are to be found, then the AST on which we
- act must first have been processed with `find_attr_docs()`.
-
- Note we also need to visit the *other* sorts of assignment, so
- we can update our Module with any globals used therein...
- """
-
- def __init__(self,settings,filename,docstring=None,package=None,debug=0):
- """Instantiate a new module.
-
- If this is a module within a package, then `package` should be
- a Package instance.
-
- `settings` will give the parsing settings -- `verbose_parse` will
- cause the generation of a message for each stage of the production
- of our data, and `debug` will give a message for each "entity"
- in the AST that we visit.
- """
- self.settings = settings
- self.package = package
- self.verbose = settings.verbose_parse
- self.debug = debug
-
- self.docformat,self.language = utils.docformat("plaintext")
-
- filename = os.path.expanduser(filename) # expand "~"
- filename = os.path.expandvars(filename) # expand "$fred" or "%fred%"
- filename = os.path.abspath(filename) # expand to a 'full' path
- filename = os.path.normpath(filename) # and tidy up
- self.filename = filename
- """The `filename` is our best guess as to the actual
- path to the module."""
-
- dir,file = os.path.split(filename)
- name,ext = os.path.splitext(file)
-
- if package:
- fullname = package.fullname + "." + name
- Base.__init__(self,settings, name,fullname,docstring)
- else:
- # Without a package, our name and fullname are the same
- Base.__init__(self,settings, name,name,docstring)
-
- self.ast = None
- """The parse tree, as produced by compiler.
- """
-
- self.globals_used = {}
- """Remember the globals promulgated on this module
- (that is, occurrences of a global statement, associated
- with assignment *to* the named global, within the same
- scope).
-
- The key is the global name, the value a list of
- (scope,superscope) pairs.
- """
-
- # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- # Experimental scope setup
- self.scope_init()
- self.scope_define_parent(parent=package,module=self)
- # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- # Now, parse ourselves!
- self.parse_module()
-
- # And then perform our "finishing off" operations
- self.determine_docformat()
-
- if self.verbose:
- print >>sys.stderr, \
- " >> docformat: %s, language %s"%(self.docformat,
- self.language)
-
- if self.docformat == utils.RESTRUCTUREDTEXT:
- if self.verbose:
- print >>sys.stderr," .. parsing docstrings in module",\
- self.name
- parser = self.getParser()
- self.parse_docstrings(parser)
- if self.verbose:
- print >>sys.stderr," .. finding <interpreted> nodes"
- self.find_docstrings()
-
- def parse_module(self):
- """Parse ourselves (!)
- """
- if self.verbose: print >>sys.stderr, "*** Parsing file",self.filename
- self.ast = compiler.parseFile(self.filename)
-
- # "Comb" the tree to sort out attribute docstrings
- if self.verbose: print >>sys.stderr, " Locating attribute docstrings"
- utils.find_attr_docs(self.ast)
-
- # And to link names and their values in assignments
- if self.verbose: print >>sys.stderr, " Locating attribute values"
- utils.find_attr_vals(self.ast)
-
- if self.verbose: print >>sys.stderr, " Walking the tree"
- compiler.walk(self.ast,self)
-
- def determine_docformat(self):
- """Call this after reading in the module, before "using" it.
-
- This detects whether there is a module value called __docformat__, and
- if so, inspect its value.
- """
- if self.attributes.has_key("__docformat__"):
- name = self.attributes["__docformat__"]
- try:
- value = name.actualLastValue()
- except ValueError, detail:
- print >>sys.stderr, "Ignoring __docformat__"
- print >>sys.stderr, detail
- return
- self.docformat,self.language = utils.docformat(value)
-
- def addGlobalUsed(self,name,where):
- if self.globals_used.has_key(name):
- self.globals_used[name].append(where)
- else:
- self.globals_used[name] = [where]
-
- def getObscureGlobals(self):
- """Return a list of (name,[fullname]) tuples
- """
- globals = self.globals_used.keys()
- globals.sort()
- attributes = self.attributes.keys()
- obscure = []
- for name in globals:
- if name not in attributes:
- wherelist = self.globals_used[name]
- obscure.append( (name,wherelist) )
- return obscure
-
- # ----------------------------------------------------------------------
- # Extraction code
-
- def _scopes(self,scope,superscope):
- str = ""
- if scope:
- str = str + " in %-8s %-12s"%(scope.__class__.__name__,
- `scope.name`)
- if superscope:
- str = str + " in %-8s %-12s"%(superscope.__class__.__name__,
- `superscope.name`)
- return str
-
- def _report(self,what,name,scope,superscope):
- print >>sys.stderr,\
- "%-8s %-12s"%(what,name) + self._scopes(scope,superscope)
-
- def visitModule(self,node,scope=None,superscope=None):
- """Visit a Module node - heh, this must be us!
-
- We expect `scope` and `superscope` both to be None
- """
- if self.debug:
- self._report("Module",self.filename,scope,superscope)
-
- self.docstring = make_Docstring(node.doc, self.settings)
-
- # Visit our children with ourselves as their scope
- self.visit(node.node,self)
-
- def visitClass(self,node,scope=None,superscope=None):
- """Visit a Class node
-
- `scope` is the scope of this Class, and `superscope` is
- that scope's scope (if any).
-
- We don't yet cope well with things like::
-
- class Fred(docutils.nodes)
-
- - this will need fixing.
- """
- if self.debug:
- self._report("Class",node.name,scope,superscope)
-
- if scope:
- fullname = "%s.%s"%(scope.fullname,node.name)
- else:
- fullname = node.name
-
- # If we were nice, we'd resolve the
- # Getattr(Getattr(Name('docutils'), 'nodes'), '_TextElement')
- # that we get for something like docutils.nodes into something
- # easier to deal with...
- cls = Class(self.settings,node.name,fullname,node.bases,node.doc)
- if scope:
- scope.addClass(cls)
-
- # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- # Experimental scope work
- if scope:
- cls.scope_define_parent(scope,self)
- scope.scope_define_name(node.name,fullname,cls)
- # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- # Visit our children with ourselves as their scope,
- # and our scope as their superscope
- self.visit(node.code,cls,scope)
-
- def visitFunction(self,node,scope=None,superscope=None):
- """Visit a Function node (nb: this means "function or method")
-
- `scope` is the scope of this Function, and `superscope` is
- that scope's scope (if any).
- """
- if self.debug:
- if isinstance(scope,Class):
- self._report("Method",node.name,scope,superscope)
- else:
- self._report("Function",node.name,scope,superscope)
-
- fullname = "%s.%s"%(scope.fullname,node.name)
-
- if isinstance(scope,Class):
- fun = Method(self.settings,node.name,fullname,
- node.argnames,node.defaults,node.flags,node.doc)
- else:
- fun = Function(self.settings,node.name,fullname,
- node.argnames,node.defaults,node.flags,node.doc)
- scope.addFunction(fun)
-
- # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- # Experimental scope work
- fun.scope_define_parent(scope,self)
- scope.scope_define_name(node.name,fullname,fun)
- for argname in node.argnames:
- fullname = "%s.%s:%s"%(scope.fullname,node.name,argname)
- name = Argument(self.settings,argname,fullname)
- name.scope_define_parent(fun,self)
- fun.scope_define_name(argname,fullname,name)
- # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- # Visit our children with this function as the scope, and
- # our scope as the superscope
- self.visit(node.code,fun,scope)
-
- def visitAssAttr(self,node,scope,superscope=None):
- """Visit an attribute assignment node.
-
- For example::
-
- self.a = 1
-
- Note that this is assignment to a *single* attribute only.
-
- `scope` is the scope of this assignment, and `superscope` is
- that scope's scope (if any).
- """
- if self.debug:
- self._report("attr",node.attrname,scope,superscope)
-
- # An AssAttr contains:
- # .expr - the expression on the LH of the dot
- # .attrname - the attribute name on the RH of the dot
- # .flags
- # We're (to a first approximation) only interested in
- # assignments of the form <self>.<attr>, where "<self>"
- # is whatever name was passed down as the first argument
- # to a containing method.
- if isinstance(node.expr,compiler.ast.Name):
- fullname = "%s:%s.%s"%(scope.fullname,node.expr.name,node.attrname)
- selfname = "%s.%s"%(node.expr.name,node.attrname)
- if node.expr.name == scope.getSelf():
- what = InstanceValue
- else:
- what = Name # hmm, this feels wrong, but I do want to distinguish
-
- if hasattr(node,"docstring"):
- #name = what(node.attrname,fullname,node.expr.name,node.docstring)
- name = what(selfname,fullname,node.expr.name,node.docstring)
- else:
- #name = what(node.attrname,fullname,node.expr.name)
- name = what(selfname,fullname,node.expr.name)
- if hasattr(node,"assign_expr"):
- name.setValue(node.assign_expr)
- scope.addAttribute(selfname,name)
-
- if node.expr.name == scope.getSelf() and scope.__class__ == Class:
- name.set_class(scope)
-
- # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- # We should do *something* for our experimental scope
- # work at this point - but I guess it would be to add
- # this name to the class that contains the method in
- # which we are - and if we're actually in a *function*
- # which is to be assigned to a class at run-time (for
- # instance), that is a bit difficult (!). So ignore
- # this case for now...
- # OR maybe we should be adding in "fullname" and not
- # "name" each time we add something to the scope.
- name.scope_define_parent(scope,self)
- scope.scope_define_name(selfname,fullname,name)
- # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- else:
- # What to do here???
- # - it's presumably something like fred[3].attr, so I guess
- # we don't want to do anything very clever with it, at least
- # for the moment.
-
- print
- print ">>> Unhandled AST node <<<"
- print " visitAssAttr: %s"%(node)
- print " i.e.: %s"%(utils.stringify_expr(node))
- print " location: Module %s, %s %s, %s %s"%\
- (self.scope_module.name,
- scope.__class__.__name__,scope.name,
- superscope.__class__.__name__,superscope.name)
- print
-
- # Hmm - what scope and superscope does the
- # subexpression *really* want...
- # - is there any point (from a DPV point of view)
- # in following down the innards of the expression?
- self.visit(node.expr,scope,superscope)
-
- def visitAssName(self,node,scope=None,superscope=None):
- """Visit a name assignment node.
-
- For example::
-
- a = 1
-
- Note that this is assignment to a *single* name only.
-
- `scope` is the scope of this assignment, and `superscope` is
- that scope's scope (if any).
- """
- if self.debug:
- self._report("name",node.name,scope,superscope)
-
- # For the moment, allow any assignments - later we may restrict
- # this (e.g., to Module, Class, __init__ method)
- if scope:
- fullname = "%s:%s"%(scope.fullname,node.name)
- else:
- fullname = node.name
-
- if scope.__class__ == Module:
- what = ModuleValue
- elif scope.__class__ == Class:
- what = ClassValue
- else:
- what = Name
-
- if hasattr(node,"docstring"):
- name = what(self.settings,node.name,fullname,
- docstring=node.docstring)
- else:
- name = what(self.settings,node.name,fullname)
- if hasattr(node,"assign_expr"):
- name.setValue(node.assign_expr)
- if scope.isGlobal(node.name):
- name.setGlobal()
- scope.addAttribute(node.name,name)
-
- # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- # Experimental scope work
- if scope:
- name.scope_define_parent(scope,self)
- scope.scope_define_name(node.name,fullname,name)
- # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- # Hmm - check whether the name is a global, and if so,
- # tell our Module about it...
- if scope.isGlobal(node.name):
- self.addGlobalUsed(node.name,scope.fullname)
-
- def visitAssTuple(self,node,scope=None,superscope=None):
- """Visit a tuple assignment statement.
-
- For example:
-
- a, b, c = 1, 2, 3
-
- Although we're not directly interested in these for docstring
- purposes, we *may* want to know that a variable has participated
- in one (why?).
- """
- for item in node.nodes:
- self.visit(item,scope,superscope)
-
- def visitAssList(self,node,scope=None,superscope=None):
- """Visit a list assignment statement.
-
- For example:
-
- a, b, c = [1, 2, 3]
-
- Although we're not directly interested in these for docstring
- purposes, we *may* want to know that a variable has participated
- in one (why?).
- """
- for item in node.nodes:
- self.visit(item,scope,superscope)
-
- def visitGlobal(self,node,scope=None,superscope=None):
- """Visit a global statement node
-
- `scope` is the scope of this global, and `superscope` is
- that scope's scope (if any).
- """
- if self.debug:
- for name in node.names:
- self._report("global",name,scope,superscope)
-
- for name in node.names:
- scope.addGlobal(name)
- # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- # Experimental scope work
- scope.scope_define_global(name)
- # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- def visitYield(self,node,scope=None,superscope=None):
- """Visit a yield statement.
-
- The presence of a yield statement within a function indicates
- that it is a generator (well, unless that statement is
- unreachable - but we shall not worry about that, at least
- for the moment!).
-
- `scope` is the scope of this statement, and `superscope` is
- that scope's scope (if any).
- """
- if self.debug:
- self._report("yield",node.value,scope,superscope)
-
- # So tell our scope that it is (probably) a generator
- scope.generator = 1
-
- # There seems little point in visiting our value, but on
- # the other hand, why not
- self.visit(node.value,scope,superscope)
-
-
- def visitImport(self,node,scope=None,superscope=None):
- """Visit an import statement node
-
- `scope` is the scope of this import statement, and
- `superscope` is that scope's scope (if any).
- """
- if self.debug:
- self._report("import","",scope,superscope)
- print >>sys.stderr, "%8s %12s %s"%(" "," ",node.names)
-
- if scope:
- scope.addImport(node.names)
- # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- # Experimental scope work
- for item in node.names:
- fullname = scope.fullname + "." + item[0]
- name = ImportName(self.settings,item[0],fullname)
- name.scope_define_parent(scope,self)
- scope.scope_define_name(item[0],fullname,name)
- # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- def visitFrom(self,node,scope=None,superscope=None):
- """Visit a from .. import statement node
-
- The rules for `scope` and `superscope` should be identical
- to those for `visitImport()`.
- """
- if self.debug:
- self._report("from",node.modname,scope,superscope)
- print >>sys.stderr, "%8s %12s %s"%(" "," ",node.names)
-
- if scope is not None:
- scope.addFromImport(node.modname,node.names)
- # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- # Experimental scope work
- for item in node.names:
- fullname = scope.fullname + "." + item[0]
- name = ImportName(self.settings,item[0],fullname)
- name.scope_define_parent(scope,self)
- scope.scope_define_name(item[0],fullname,name)
- # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- # ----------------------------------------------------------------------
-
- def _prt(self,stream,indent,name,place):
- stream.write("%sGlobal %-10s in %s\n"%(" "*indent,name,place))
-
- def _and(self,stream,indent,name,place):
- stream.write("%s %-10s and in %s\n"%(" "*indent," "*len(name),
- place))
-
- def _show_odd_globals(self,stream,indent=0):
- """Show which global names are defined and used below module level
-
- Obviously (!) we are only interested in things which are not
- already known to be module level attributes - we want to warn
- the user about things that are defined in non-obvious places.
- """
- obscure = self.getObscureGlobals()
- done_header = 0
- for name,wherelist in obscure:
- if not done_header:
- stream.write("Globals defined *and used* below"
- " the top level:\n")
- done_header = 1
- self._prt(stream,indent+2,name,wherelist[0])
- for place in wherelist[1:]:
- self._and(stream,indent+2,name,place)
-
- def show(self,stream,indent=0):
- stream.write("%sModule %s"%(" "*indent,self.name))
- if self.filename:
- stream.write("(in file %s)\n"%self.filename)
- else:
- stream.write("\n")
- self._show_body(stream,indent)
- self._show_odd_globals(stream,indent)
-
- def show_ast(self,stream):
- """Print out a representation of our AST.
- """
- stream.write("AST for module %s\n"%self.name)
- utils.treeprint(stream,self.ast)
-
-# ----------------------------------------------------------------------
-class Class(Base):
- """The representation of a Python class."""
-
- def __init__(self,settings,name,fullname,bases,docstring):
- Base.__init__(self,settings,name,fullname,docstring)
-
- self.bases = bases or []
- """A list of the base classes for this class."""
-
- # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- # Experimental scope setup
- self.scope_init()
- # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- def is_callable(self):
- """Does it make sense to call an object of this type?
-
- NB: it only makes sense to call this *after* the class has
- been parsed!
- """
- return self.functions.has_key("__call__")
-
- def show(self,stream,indent=0):
- basestr = ""
- if self.bases:
- names = self.getBaseNames()
- basestr = "(" + string.join(names,",") + ")"
- stream.write("%sClass %s%s\n"%(" "*indent,self.name,basestr))
- self._show_body(stream,indent)
-
- def getBaseNames(self):
- names = []
- for base in self.bases:
- # Unfortunately, we don't yet cope with base classes
- # like "docutils.nodes" in our visitor...
- # Make the best of it we can, for now
- try:
- names.append(base.name)
- except:
- names.append("???")
- return names
-
- # Is it worth doing this?
- addMethod = Base.addFunction
- getMethodNames = Base.getFunctionNames
-
-
-# ----------------------------------------------------------------------
-class Function(Base):
- """The representation of a Python function (and thus also of a method).
-
- But see also `Method`.
- """
-
- def __init__(self,settings,name,fullname,args,defaults,flags,docstring):
- Base.__init__(self,settings,name,fullname,docstring)
-
- self.args = args
- """The arguments for this function or method."""
-
- self.defaults = defaults
- """The defaults (if any) for the latter arguments.
-
- Note that if there are 4 arguments, and only the last
- 2 have defaults, then this list will be 2 items long.
- """
-
- self.flags = flags
- """Used to indicate \*args and \**kwargs.
- """
-
- self.generator = 0
- """Set to true if this function appears to be a generator
- (i.e., it contains a "yield" statement). Obscure code that
- doesn't actually *reach* the yield statement - for instance::
-
- def fred():
- print "3"
- if 1: return
- yield "2"
-
- will also, incorrectly, be recognised as a generator - tough.
- """
-
- # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- # Experimental scope setup
- self.scope_init()
- # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- def is_callable(self):
- """Does it make sense to call an object of this type?
- """
- return 1
-
- def args_label(self):
- """Return the specialised label we use for all of our arguments.
- """
- return self.label() + "---args"
-
- def getArgs(self):
- """Return a representation of our arguments as a list (of strings).
-
- This is then suitable for joining with commas and displaying.
- """
- args = utils.merge_args(self.args,self.defaults)
- if not args:
- return args
-
- # The file compiler/consts.py defines CO_VARARGS=1 and
- # CO_VARKEYWORDS=2.
-
- # The method Transformer.com_arglist() in file compiler/transformer.py
- # handles a function's argument list.
-
- # According to that, if there's a "*args" item, then "flags" gets the
- # CO_VARARGS bit set, and if there's a "**args" item, then "flags" gets
- # the CO_VARKEYWORDS bit set. In either case, we *know* they've got to
- # be the last arguments, so we can count backwards (as we do for
- # default arguments).
-
- if self.flags & compiler.consts.CO_VARKEYWORDS:
- # If it's there, this must always be the last one...
- args[-1] = "**" + args[-1]
-
- if self.flags & compiler.consts.CO_VARARGS:
- # But this one might be last OR last but one
- if self.flags & compiler.consts.CO_VARKEYWORDS:
- args[-2] = "*" + args[-2]
- else:
- args[-1] = "*" + args[-1]
-
- return args
-
- def show(self,stream,indent=0):
- stream.write("%s%s %s(%s)\n"%(" "*indent,self.__class__.__name__,
- self.name,
- string.join(self.getArgs(),", ")))
- self._show_body(stream,indent)
-
- def getSelf(self):
- """For a method, return the name used for "self".
-
- (Actually, for a method *or* a function, return the name of
- the first argument - we need it on functions as well in case
- someone is defining a function later to be assigned to a class
- and used as a method.)
- """
- if len(self.args) > 0:
- return self.args[0]
- else:
- return None
-
-
-# ----------------------------------------------------------------------
-class Method(Function):
- """Just to get the class name right, I'm afraid...
- """
- pass
-
-
-# ----------------------------------------------------------------------
-class Name(ScopeMixin):
- """Information about use of a name in assignment.
-
- STILL UNDER CONSTRUCTION
-
- Test using pysource.py's "--show" option...
-
-
- We are not interested in *all* names, nor in all information
- about them...
-
- (We *could* inherit from Base, but that really brings too much other
- stuff that we don't need with it - and it doesn't *quite* seem worth
- having a mixin class (although the more I work with this, the more
- that seems a wrong decision - maybe next refactor time will change
- things.)
- """
-
- def __init__(self,settings,name,fullname,selfname=None,docstring=None):
- """Instantiate a new Name.
-
- * `settings` -- the settings for the parser
- * `name` -- the name of this, erm, name
- * `fullname` -- the "fully qualified" name - this is the "path" from
- our top-level entity down to this name (e.g., module.class.name)
- * `selfname` -- if this is an instance attribute, the string used
- as the "self" equivalent
- * `docstring` -- the docstring for this name, if any.
- """
-
- self.name = name
- """The name of this, erm, name.
- """
-
- self.fullname = fullname
- """The fully qualified name of this name
- - for instance, for a name `fred` in a class `Jim`
- in a module `bob`, this would be "bob.Jim.fred"
- """
-
- self.docstring = make_Docstring(docstring, settings)
- """The docstring for this name, or None.
- Note that, at least for the moment, we're only supporting
- one docstring for an entity. See the equivalent comment
- in `Base`.
- """
-
- self.firstuse = None
- """Remember the first use of this name - i.e., what is
- assigned to it. The value stored is the AST expression
- assigned to our name.
- """
-
- self.lastuse = None
- """Also remember the last use of this name. The value
- stored is the AST expression, as for firstuse.
- """
-
- self.reused = 0
- """Assume it has not been assigned to more than once.
- If it has, then we can't *really* report on its 'content',
- and `self.firstuse` should be ignored.
- """
-
- self.selfname = selfname
- """If this name is referred to as something like 'self.name'
- then we want to remember the string used as 'self' (since the
- user *might* be using something else). This will be ``None``
- if there is no 'prefix'.
- """
-
- self.isglobal = 0
- """True if this name is global to its module.
- """
-
- # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- # Experimental scope setup
- self.scope_init()
- # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- def parse_docstrings(self,parser):
- """If we are meant to, parse our docstrings.
-
- (The oddly plural name is for compatibility with those things
- that inherit from `Base` - another reason for thinking that a
- mixin class may be about due...)
- """
- if self.docstring:
- self.docstring.parse(parser)
-
- # ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
- # Experimental <interpreted> node code...
- def find_docstrings(self):
- """Find each docstring in our subtree.
-
- (The oddly plural name is for compatibility with those things
- that inherit from `Base` - another reason for thinking that a
- mixin class may be about due...)
- """
- if self.docstring:
- self.docstring.transform_interpreted(self)
- # ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
-
- def is_callable(self):
- """Does it make sense to call an object of this type?
- """
- return 0
-
- def label(self):
- """Return an XML-legal name for this object.
-
- Note that we implicitly assume that all objects have their
- output XML/HTML representation written to the same file
- - i.e., that we do not have to worry about references that
- are anything beyond simple names.
-
- (another duplicate of a method in Base)
- """
- str = string.replace(self.fullname,".","-")
- str = string.replace(str,":","--")
- return str
-
- def setValue(self,expr):
- self.lastuse = expr
- if not self.firstuse:
- self.firstuse = expr
- else:
- self.reused = 1
-
- def setGlobal(self):
- self.isglobal = 1
-
- def isGlobal(self):
- return self.isglobal
-
- def getDocstring(self):
- return self.docstring
-
- def getSelfName(self):
- return self.selfname
-
- def getValueString(self):
- if self.reused or not self.firstuse:
- return None
- else:
- return utils.stringify_expr(self.firstuse)
-
- def getLastValueString(self):
- """Return the stringified value of this name, or None.
- """
- return utils.stringify_expr(self.lastuse)
-
- def actualLastValue(self):
- """Return the actual value assigned to this name.
-
- If the value assigned is a constant, then return it, otherwise
- raise a ValueError (we can't just return NULL because that *is*
- a sensible constant!).
- """
- thing = self.lastuse
- # See utils.stringify_expr() for information on what we think
- # we're doing here...
- if isinstance(thing,compiler.ast.Const):
- return thing.value
- else:
- raise ValueError,"Value assigned to %s is not a constant:\n" \
- "(%s)"%(self.getSelfName(),self.getLastValueString())
-
- def getAsString(self):
- str = self.name
- val = self.getValueString()
- if val:
- str += " = " + val
- return str
-
- def show(self,stream,indent=0):
- """Override as necessary."""
- stream.write("%s%s %s"%(" "*indent,self.__class__.__name__,
- self.getAsString()))
- if self.isglobal:
- stream.write(" (global)\n")
- else:
- stream.write("\n")
- if self.docstring:
- self.docstring.show(stream," "*(indent+2))
-
-
-# ----------------------------------------------------------------------
-class Argument(Name):
- """An argument to a method or function.
-
- This is a separate class just to get the class name right, I'm afraid...
- """
- pass
-
-
-# ----------------------------------------------------------------------
-class ModuleValue(Name):
- """A name defined by assignment at the top level of a module.
-
- This is a separate class just to get the class name right, I'm afraid...
- """
- pass
-
-
-# ----------------------------------------------------------------------
-class ClassValue(Name):
- """A name defined by assignment within a class definition.
-
- This is a separate class just to get the class name right, I'm afraid...
- """
- pass
-
-
-# ----------------------------------------------------------------------
-class InstanceValue(Name):
- """An instance defined by assignment within a method - e.g., self.thing
-
- TO DO: Hmm - I need to actually *implement* the use of `self.our_class`
- and `self.see_also`.
- """
-
- def __init__(self,*args,**kws):
- Name.__init__(self,*args,**kws)
-
- self.our_class = None
- """If we are self.thing in a method, then "self" refers to a class
- (the one enclosing the method!), and this will be a reference to it.
- """
-
- self.see_also = None
- """If the class already defined a `ClassInstance` of this name,
- then we'll ultimately want a reference to that class here, so
- that our output can say "see also class instance XXX".
- """
-
- def set_class(self,klass):
- """Indicate which Class we really belong to.
- """
- self.our_class = klass
-
-
-# ----------------------------------------------------------------------
-class ImportName(Name):
- """A name assigned by "import" or "from ... import"
-
- Should we distinguish these? ((yes))
-
- This is a separate class just to get the class name right, I'm afraid...
-
- NB: we don't yet deal with "import ... as ..."
- """
-
- def is_callable(self):
- """Does it make sense to call an object of this type?
-
- Unfortunately, if it's something imported with "from ... import"
- there is no simple way of knowing - so maybe err on the side of
- assuming so.
-
- ((Note that this is actually a good argument for separating out
- the two sorts of import, since we know *modules* are not callable,
- and "import" just makes modules visible.))
- """
- return 1
-
-
-# ----------------------------------------------------------------------
-def test_parse_module(filename):
- print "Reading file %s"%filename
- return Module(filename,debug=0)
-
-def test_show_ast(thing):
- print
- print "AST"
- print "==="
- thing.show(sys.stdout)
-
-def test_show_scopes(thing):
- print
- print "Scopes"
- print "======"
- thing.scope_show()
-
-def test():
- print "Testing pysource/visit.py"
- if len(sys.argv) <= 1:
- print "Usage: pysource/visit.py <python-file>"
- return
- filename = sys.argv[1]
- thing = test_parse_module(filename)
- test_show_ast(thing)
- test_show_scopes(thing)
-
-if __name__ == "__main__":
- test()
diff --git a/sandbox/tibs/pysource2/__init__.py b/sandbox/tibs/pysource2/__init__.py
deleted file mode 100644
index d7e9d8a32..000000000
--- a/sandbox/tibs/pysource2/__init__.py
+++ /dev/null
@@ -1,10 +0,0 @@
-"""Package pysource2 - Python source to Python source documentation
-
-:Author: Tibs
-:Contact: tibs@tibsnjoan.co.uk
-:Revision: $Revision$
-:Date: $Date$
-:Copyright: This module has been placed in the public domain.
-"""
-
-__docformat__ = 'reStructuredText'
diff --git a/sandbox/tibs/pysource2/log.txt b/sandbox/tibs/pysource2/log.txt
deleted file mode 100644
index 9bae3e9e0..000000000
--- a/sandbox/tibs/pysource2/log.txt
+++ /dev/null
@@ -1,113 +0,0 @@
-=============================
-Writing and testing pysource2
-=============================
-
-:Author: Tibs
-:Contact: tibs@tibsnjoan.co.uk
-:Revision: $Revision$
-:Date: $Date$
-:Copyright: This document has been placed in the public domain.
-
-pysource2 is my attempt to rewrite the original pysource. pysource
-itself was a proof-of-concept module to find docstrings withing Python
-source files and present them as (by default) HTML documentation, as
-described by the Docutils project. Since it was written before the
-Docutils codebase became stabilised around its current Reader/Writer
-patterns, it doesn't really mesh well with the current approaches. Also,
-lots of the code is fairly grotty anyway, and could do with a rewrite on
-principle - not least because it is not well tested.
-
-So, pysource2 is both that rewrite, and also an attempt on my part to
-learn how to do test driven development.
-
-Setting the path
-================
-
-I want to take my docutils stuff directly from the source directories,
-so that I work with the latest CVS code, and don't have to keep installing
-things. Thus I need to set the Python path to point to the source
-directories::
-
- export PYTHONPATH=${PYTHONPATH}:${HOME}/docutils
-
-Since I'm using Python 2.2.3, I also need the modules in the "extras"
-directory::
-
- export PYTHONPATH=${PYTHONPATH}:${HOME}/docutils/extras
-
-If I want access to the testing stuff, I also need the "test"
-directory::
-
- export PYTHONPATH=${PYTHONPATH}:${HOME}/docutils/test
-
-
-NB: Relies upon the code in docutils/docutils/readers/python/moduleparser.py
-
-Log
-===
-The "obvious" place to start is with packages - the previous pysource
-never did quite get them right (for a start, it wouldn't cope with
-sub-packages). Also, having a utility to report on packages, then on
-modules, and gradually on to finer levels of detail, seems like giving
-something useful as soon as possible.
-
-It looked over-complex to adopt the docutils test framework itself,
-initially, especially since I am new both to unit testing *and* to test
-driven development. So I am being less ambitious, and working with
-"pure" unit tests - I reckon I'll learn more that way.
-
-So, the first pass gives me package.py and test_package.py.
-
-My first impressions of (such a little bit of) development is that TDD
-does indeed give one the feeling of reassurance I'd expected from my
-half-TDD efforts in Java at LSL.
-
-Initially, I was looking to detect a request for a package that didn't
-exist, or wasn't a directory file, explicitly, with dedicated
-exceptions. This felt rather over-complex, and indeed refactoring those
-tests out and just catching a (non-explicit) OSError in the tests works
-well enough - in reality, a user is not going to ask to parse a package
-that is not already known to be an existant directory (heck, the "user"
-is probably a program that's just figured out if the thing whose
-documentation is wanted is a file or a directory), and if they do then
-OSError makes sense since it is what one would normally get.
-
-
-Questions
-=========
-
-* Should we attempt to parse files that don't end in ".py"?
-
- What about ".pyw"?
-
- What about Python files on Unix which have had their extension removed and
- been made executable?
-
-* Should there be an option to produce a document for a directory of Python
- files that is not a package - e.g., a directory of useful scripts put
- together just to be on the UNIX path, or Python's own library.
-
-
-TODO
-====
-
- * Add a method to Module to indicate if it has an Attribute called
- __docformat__, and if so, what its value is.
-
- * That requires understanding how the testing for the moduleparser is
- organised and works, so I can add an appropriate test.
-
- * At which stage, should I incorporate Package (and NotPython) therein?
-
- * Write a simple transform (first learn how!) to parse any Docstring
- contents in a module with __docformat__ equal to one of the reStructuredText
- indicators.
-
- * Write another transform to turn the Pythonic doctree into a standard one.
-
- * At which point, we'll have something useful, albeit not very powerful,
- so provide an appropriate command line interface for (at least) HTML output.
-
- * Work out how to do attribute references, etc., in *this* context (I have
- no idea if the mechanisms from the original pysource will be any use).
-
diff --git a/sandbox/tibs/pysource2/not_a_directory b/sandbox/tibs/pysource2/not_a_directory
deleted file mode 100644
index e69de29bb..000000000
--- a/sandbox/tibs/pysource2/not_a_directory
+++ /dev/null
diff --git a/sandbox/tibs/pysource2/package.py b/sandbox/tibs/pysource2/package.py
deleted file mode 100644
index 96524693f..000000000
--- a/sandbox/tibs/pysource2/package.py
+++ /dev/null
@@ -1,185 +0,0 @@
-"""package.py - support for calculating package documentation.
-
-:Author: Tibs
-:Contact: tibs@tibsnjoan.co.uk
-:Revision: $Revision$
-:Date: $Date$
-:Copyright: This module has been placed in the public domain.
-"""
-
-__docformat__ = 'reStructuredText'
-
-import os
-from docutils.readers.python.moduleparser import Node, parse_module
-
-DEBUG = 0
-
-class NotAPackageException(Exception):
- pass
-
-
-# ----------------------------------------------------------------------
-class Package(Node):
- """This class represents a Python package.
-
- `filename` is the name of the package - i.e., the package name.
- This may be extended/altered/expanded to include/disambiguate the
- name of the package, the "full" name of the package (e.g., if it is
- a sub-package) and the full path of the package, as needs indicate.
-
- Note that a package must, by definition, include at least one module,
- i.e., __init__.py (otherwise, it isn't a package).
- """
-
- def __init__(self, filename):
- """Initialise a Package.
-
- Note that this does *not* take a "node" argument, since a Package
- is not actually quite like the Module and other sub-nodes.
-
- @@@ (Actually, there's a case to say that Node should be able to take
- a "node" value of None and cope, in which case our life would be
- easier - I may work on that later on...)
- """
- # Hackery - the following two lines copied from Node itself.
- self.children = []
- self.lineno = None
- self.filename = filename
-
- def attlist(self):
- return Node.attlist(self, filename=self.filename)
-
-
-
-# ----------------------------------------------------------------------
-class NotPython(Node):
- """This class is used to represent a non-Python file.
-
- @@@ If the file isn't Python, should we try for reStructuredText?
- """
-
- def __init__(self, filename):
- """Initialise a NotPython instance.
-
- @@@ Same caveats as Package.
- """
- # Hackery - the following two lines copied from Node itself.
- self.children = []
- self.lineno = None
- self.filename = filename
-
- def attlist(self):
- return Node.attlist(self, filename=self.filename)
-
-
-# ----------------------------------------------------------------------
-def parse_package_or_module(path):
- """Parse a package or module for documentation purposes.
-
- `path` should either be a directory representing a Python package, or
- a single Python file.
- """
- path = os.path.normpath(path)
- if os.path.isdir(path):
- return parse_package(path)
- else:
- return parse_file(path,path)
-
-def parse_package(package_path):
- """Parse a package for documentation purposes.
-
- `package_path` should be the system path of the package directory, which is
- not necessarily the same as the Python path...
- """
-
- if DEBUG: print "Parsing package",package_path
-
- package_path = os.path.normpath(package_path)
- dir,file = os.path.split(package_path)
- if dir == "":
- dir = "."
- return parse_subpackage(dir,file)
-
-def parse_subpackage(package_path,subpackage):
- """Parse a subpackage for documentation purposes.
-
- `package_path` should be the system path of the package directory,
- and `subpackage` is the (file) name of the subpackage therein. It
- is assumed that this is already known to be a directory.
- """
-
- sub_path = os.path.join(package_path,subpackage)
-
- if DEBUG: print "Parsing sub-package",sub_path
-
- files = os.listdir(sub_path)
- if "__init__.py" not in files:
- raise NotAPackageException,\
- "Directory '%s' is not a Python package"%sub_path
-
- node = Package(subpackage)
-
- # Should we sort the files? Well, if we don't have them in a predictable
- # order, it is harder to test the result(!), and also I believe that it
- # is easier to use the output if there is some obvious ordering. Of course,
- # the question then becomes whether packages and modules should be in the
- # same sequence, or separated.
- files.sort()
-
- for filename in files:
- fullpath = os.path.join(sub_path,filename)
- if os.path.isdir(fullpath):
- try:
- node.append(parse_subpackage(sub_path,filename))
- except NotAPackageException:
- pass
- else:
- # We do *not* want to try .pyc or .pyo files - we can guarantee
- # that they won't parse (the Python compiler code gets unhappy
- # about NULL bytes therein), and we definitely don't want an
- # entry for such files in our documentation.
- # Similarly, I work on Linux, and don't want to consider files
- # that end with "~" (this last is a bit nasty...)
- if os.path.splitext(filename)[1] not in (".pyc",".pyo") and \
- filename[-1] != "~":
- node.append(parse_file(fullpath,filename))
- return node
-
-def parse_file(fullpath,filename):
- """Parse a single file (which we hope is a Python file).
-
- * `fullpath` is the full path of the file
- * `filename` is the name we want to use for it in the docutils tree
-
- Returns a docutils parse tree for said file.
- """
-
- if DEBUG: print "Parsing file",fullpath
-
- # @@@ Should we worry about the extension of the file?
- # Trying to use that to predict the contents can be a problem
- # - we already know that we have to worry about ".pyw" as well
- # as ".py", not to mention the possibility (e.g., on Unix) of
- # having removed the extension in order to make an executable
- # file "look" more like a Unix executable. On the whole, it's
- # probably better to try to parse a file, and worry about it
- # not parsing if/when that occurs.
- module = open(fullpath)
- try:
- module_body = module.read()
- try:
- module_node = parse_module(module_body,filename)
- except SyntaxError:
- # OK - it wasn't Python - so what *should* we do with it?
- module_node = NotPython(filename)
- if DEBUG: print " (not Python)"
- return module_node
- finally:
- module.close()
-
-
-
-# ----------------------------------------------------------------------
-if __name__ == "__main__":
- result = parse_package("trivial_package")
- print result
diff --git a/sandbox/tibs/pysource2/pysrc2html.py b/sandbox/tibs/pysource2/pysrc2html.py
deleted file mode 100755
index 9aaf26782..000000000
--- a/sandbox/tibs/pysource2/pysrc2html.py
+++ /dev/null
@@ -1,46 +0,0 @@
-#!/usr/bin/env python
-"""pysrc2html - Read Python package/modules and output HTML documentation
-
-@@@ I'm not terribly happy with the name of this module, but it will do for
-now (pydoc2html *might* be better?)
-
-:Author: Tibs
-:Contact: tibs@tibsnjoan.co.uk
-:Revision: $Revision$
-:Date: $Date$
-:Copyright: This module has been placed in the public domain.
-"""
-
-__docformat__ = 'reStructuredText'
-
-import sys
-from package import parse_package_or_module
-import transform
-from docutils.writers.html4css1 import Writer
-from docutils.frontend import OptionParser
-
-usage = '%prog [options] [<package-directory> | <python-file> [html-file]]'
-description = ('Generates .html documentation for the given Python package'
- ' or module.')
-
-writer = Writer()
-
-option_parser = OptionParser(components=[writer],
- usage=usage,description=description)
-
-settings = option_parser.parse_args(sys.argv[1:])
-
-source_path = settings._source
-target_path = settings._destination
-
-nodes = parse_package_or_module(source_path)
-
-# That then needs converting to a docutils tree
-document = transform.make_document(nodes,settings)
-
-# And *that* wants converting to the appropriate output format
-try:
- target = open(target_path,"w")
- writer.write(document,target)
-finally:
- target.close()
diff --git a/sandbox/tibs/pysource2/reader.py b/sandbox/tibs/pysource2/reader.py
deleted file mode 100644
index 6e4c7dfd2..000000000
--- a/sandbox/tibs/pysource2/reader.py
+++ /dev/null
@@ -1,31 +0,0 @@
-"""reader.py - docutils Reader for Python source code
-
-:Author: Tibs
-:Contact: tibs@tibsnjoan.co.uk
-:Revision: $Revision$
-:Date: $Date$
-:Copyright: This module has been placed in the public domain.
-"""
-
-__docformat__ = 'reStructuredText'
-
-import docutils.readers
-from docutils.readers.python.moduleparser import Node, parse_module
-#from package import parse_package
-from transform import make_document
-
-class Reader(docutils.readers.Reader):
- """A Python source code specific Reader.
- """
-
- config_section = 'python reader'
- config_section_dependencies = ('readers',)
-
- def parse(self):
- """Parse `self.input` into a document tree."""
-
- tree = parse_module(self.input,self.source.source_path)
- self.document = document = make_document(tree)
- #self.document = document = self.new_document()
- #self.parser.parse(self.input, document)
- document.current_source = document.current_line = None
diff --git a/sandbox/tibs/pysource2/temp.rst b/sandbox/tibs/pysource2/temp.rst
deleted file mode 100644
index fa2836232..000000000
--- a/sandbox/tibs/pysource2/temp.rst
+++ /dev/null
@@ -1,81 +0,0 @@
-<document source="temp.txt">
- <comment xml:space="preserve">
- This is a simple reStructuredText file that represents what I would
- <comment xml:space="preserve">
- like the output of transforming my test Python code to be
- <section class="package" id="package-trivial-package" name="package trivial_package">
- <title>
- Package trivial_package
- <section class="module" id="module-trivial-package-init" name="module trivial_package.__init__">
- <title>
- Module trivial_package.__init__
- <block_quote class="docstring">
- <paragraph>
- A simple docstring.
- <section class="module" id="module-trivial-package-file1" name="module trivial_package.file1">
- <title>
- Module trivial_package.file1
- <block_quote class="docstring"> ## Hmm - not quite right
- <paragraph>
- This is the first example file. It
- <emphasis>
- does
- use reStructuredText.
- <paragraph>
- Attributes:
- <bullet_list bullet="*">
- <list_item>
- <paragraph>
- __docformat__ = "reST" (line 5)
- <paragraph>
- Import: os (line 7)
- <section class="class" id="class-trivial-package-file1-fred" name="class trivial_package.file1.fred">
- <title>
- Class trivial_package.file1.Fred
- <field_list>
- <field>
- <field_name>
- line
- <field_body>
- <paragraph>
- 9
- <paragraph class="docstring"> ## Hmm
- An example class - it announces each instance as it is created.
- <section class="method" id="method-trivial-package-file1-fred-init" name="method trivial_package.file1.fred.__init__">
- <title>
- Method trivial_package.file1.Fred.__init__
- <field_list>
- <field>
- <field_name>
- line
- <field_body>
- <paragraph>
- 13
- <field>
- <field_name>
- parameters
- <field_body>
- <paragraph>
- self
- <section class="module" id="module-trivial-package-file2" name="module trivial_package.file2">
- <title>
- Module trivial_package.file2
- <block_quote class="docstring">
- <paragraph>
- This module is
- <emphasis>
- not
- using reStructuredText for its docstrings.
- <section class="file" id="file-trivial-package-not-python" name="file trivial_package.not_python">
- <title>
- File trivial_package.not_python
- <paragraph>
- (Not a Python module)
- <section class="package" id="package-trivial-package-sub-package" name="package trivial_package.sub_package">
- <title>
- Package trivial_package.sub_package
- <section class="module" id="module-trivial-package-sub-package-init" name="module trivial_package.sub_package.__init__">
- <title>
- Module trivial_package.sub_package.__init__
- <paragraph>
- (No documentation)
diff --git a/sandbox/tibs/pysource2/temp.txt b/sandbox/tibs/pysource2/temp.txt
deleted file mode 100644
index dc1e9640f..000000000
--- a/sandbox/tibs/pysource2/temp.txt
+++ /dev/null
@@ -1,79 +0,0 @@
-.. This is a simple reStructuredText file that represents what I would
-.. like the output of transforming my test Python code to be
-
-.. class:: package
-
-=======================
-Package trivial_package
-=======================
-
-.. class:: module
-
-Module trivial_package.__init__
-===============================
-
- .. class:: docstring
-
- A simple docstring.
-
-.. class:: module
-
-Module trivial_package.file1
-============================
-
- .. class:: docstring
-
- This is the first example file. It *does* use reStructuredText.
-
- Attributes:
-
- * __docformat__ = "reST" (line 5)
-
- Import: os (line 7)
-
-.. class:: class
-
-Class trivial_package.file1.Fred
---------------------------------
-
-:line: 9
-
- .. class:: docstring
-
- An example class - it announces each instance as it is created.
-
-.. class:: method
-
-Method trivial_package.file1.Fred.__init__
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-:line: 13
-:parameters: self
-
-.. class:: module
-
-Module trivial_package.file2
-============================
-
- .. class:: docstring
-
- This module is *not* using reStructuredText for its docstrings.
-
-.. class:: file
-
-File trivial_package.not_python
-===============================
-
-(Not a Python module)
-
-.. class:: package
-
-Package trivial_package.sub_package
-===================================
-
-.. class:: module
-
-Module trivial_package.sub_package.__init__
--------------------------------------------
-
-(No documentation)
diff --git a/sandbox/tibs/pysource2/test_package.py b/sandbox/tibs/pysource2/test_package.py
deleted file mode 100644
index d267d3937..000000000
--- a/sandbox/tibs/pysource2/test_package.py
+++ /dev/null
@@ -1,179 +0,0 @@
-#! /usr/bin/env python
-"""test_package.py
-
-Unit tests for parsing packages for pysource.
-
-Initially, this is a standalone test, but ultimately it may be merged into the
-mechanisms used for the Docutils self-tests.
-
-:Author: Tibs
-:Contact: tibs@tibsnjoan.co.uk
-:Revision: $Revision$
-:Date: $Date$
-:Copyright: This module has been placed in the public domain.
-"""
-
-__docformat__ = 'reStructuredText'
-
-import unittest
-
-from package import parse_package, NotAPackageException
-from transform import make_document
-
-# The following is to ensure that there are .pyc files in the package
-# - this is important for testing, since the Python compiler gets quite
-# unhappy if given a non-text file to play with (it doesn't like null bytes),
-# so we need to do something about that...
-import trivial_package
-
-class PackageTest(unittest.TestCase):
-
- def testNoSuchDirectory(self):
- """Not a package - no such directory.
- """
-
- self.assertRaises(OSError,
- parse_package,
- "no_such_directory")
-
- def testNotADirectory(self):
- """Not a package - file is not a directory.
- """
-
- self.assertRaises(OSError,
- parse_package,
- "not_a_directory")
-
- def testNotAPackage(self):
- """Not a package - directory is empty.
- """
-
- self.assertRaises(NotAPackageException,
- parse_package,
- "not_a_package")
-
- def testPackage(self):
- """A package containing subpackage(s)
-
- The directory is called "trivial_package" for historical reasons.
- """
-
- wanted_result = """\
-<Package filename="trivial_package">
- <Module filename="__init__.py">
- <Docstring>
- A simple docstring.
- <Module filename="file1.py">
- <Docstring>
- This is the first example file. It *does* use reStructuredText.
- <Attribute lineno="5" name="__docformat__">
- <Expression lineno="5">
- "reST"
- <Import lineno="7">
- os
- <Class lineno="9" name="Fred">
- <Docstring lineno="9">
- An example class - it announces each instance as it is created.
- <Method lineno="13" name="__init__">
- <ParameterList lineno="13">
- <Parameter lineno="13" name="self">
- <Module filename="file2.py">
- <Docstring>
- This module is *not* using reStructuredText for its docstrings.
- <NotPython filename="not_python">
- <Package filename="sub_package">
- <Module filename="__init__.py">\n"""
-
- actual_result = str(parse_package("trivial_package"))
-
- if wanted_result != actual_result:
- print "+++++++++++++++++++++++++ WANT"
- print wanted_result
- print "+++++++++++++++++++++++++ GOT"
- print actual_result
- print "+++++++++++++++++++++++++"
-
- self.assertEqual(actual_result,wanted_result)
-
- def testMakeDocument(self):
- """
- Turn our Package tree into a docutils Document.
- """
-
- # I've split the wanted result string up into substrings so I can
- # amend it more easily (or so I hope).
- trivial_package = """\
-<document source="Package trivial_package">
- <section class="package" id="package-trivial-package" name="package trivial_package">
- <title>
- Package trivial_package\n"""
-
- # The "xml:space" attribute is by observation, not prediction
- module_init = """\
- <section class="module" id="module-trivial-package-init" name="module trivial_package.__init__">
- <title>
- Module trivial_package.__init__
- <literal_block class="docstring" xml:space="preserve">
- A simple docstring.\n"""
-
- module_file1 = """\
- <section class="module" id="module-trivial-package-file1" name="module trivial_package.file1">
- <title>
- Module trivial_package.file1
- <literal_block class="docstring" xml:space="preserve">
- This is the first example file. It *does* use reStructuredText.
- <section class="class" id="class-trivial-package-file1-fred" name="class trivial_package.file1.fred">
- <title>
- Class trivial_package.file1.Fred
- <literal_block class="docstring" xml:space="preserve">
- An example class - it announces each instance as it is created.\n"""
-
- module_file2 = """\
- <section class="module" id="module-trivial-package-file2" name="module trivial_package.file2">
- <title>
- Module trivial_package.file2
- <literal_block class="docstring" xml:space="preserve">
- This module is *not* using reStructuredText for its docstrings.\n"""
-
- non_python_file = """\
- <section class="file" id="file-trivial-package-not-python" name="file trivial_package.not_python">
- <title>
- File trivial_package.not_python
- <paragraph>
- File
- <literal>
- not_python
- is not a Python module.\n"""
-
- sub_package = """\
- <section class="package" id="package-trivial-package-sub-package" name="package trivial_package.sub_package">
- <title>
- Package trivial_package.sub_package\n"""
-
- sub_module_init = """\
- <section class="module" id="module-trivial-package-sub-package-init" name="module trivial_package.sub_package.__init__">
- <title>
- Module trivial_package.sub_package.__init__\n"""
-
- wanted_result = (trivial_package + module_init + module_file1 +
- module_file2 + non_python_file + sub_package +
- sub_module_init)
-
- tree = parse_package("trivial_package")
-
- document = make_document(tree)
-
- actual_result = document.pformat()
-
- if wanted_result != actual_result:
- print "+++++++++++++++++++++++++ WANT"
- print wanted_result
- print "+++++++++++++++++++++++++ GOT"
- print actual_result
- print "+++++++++++++++++++++++++"
-
- self.assertEqual(actual_result,wanted_result)
-
-
-if __name__ == "__main__":
- unittest.main()
diff --git a/sandbox/tibs/pysource2/test_reader.py b/sandbox/tibs/pysource2/test_reader.py
deleted file mode 100644
index e48f20749..000000000
--- a/sandbox/tibs/pysource2/test_reader.py
+++ /dev/null
@@ -1,127 +0,0 @@
-#! /usr/bin/env python
-"""test_reader.py
-
-Unit tests for the Python source Reader
-
-Initially, this is a standalone test, but ultimately it may be merged into the
-mechanisms used for the Docutils self-tests.
-
-:Author: Tibs
-:Contact: tibs@tibsnjoan.co.uk
-:Revision: $Revision$
-:Date: $Date$
-:Copyright: This module has been placed in the public domain.
-"""
-
-__docformat__ = 'reStructuredText'
-
-import unittest
-
-from package import parse_package
-from transform import make_document
-from reader import Reader
-from docutils.core import publish_string
-from docutils.readers.python.moduleparser import parse_module
-
-class PackageTest(unittest.TestCase):
-
- def testReader(self):
- """Test the reader works as expected
- """
- reader = Reader()
-
- source="# A Python comment"
- source_path="test.py"
-
- # Hmm - extra debugging info...
- publish_string = publish_string_with_traceback
-
- actual_result = publish_string(reader=reader,reader_name="python",
- parser_name="restructuredtext",
- writer_name="pseudoxml",
- source=source, source_path=source_path)
-
- wanted_result = """\
-<document source="Module test">
- <section class="module" id="module-test" name="module test">
- <title>
- Module test\n"""
-
-
- if wanted_result != actual_result:
- print "+++++++++++++++++++++++++ WANT"
- print wanted_result
- print "+++++++++++++++++++++++++ GOT"
- print actual_result
- print "+++++++++++++++++++++++++"
-
- self.assertEqual(actual_result,wanted_result)
-
- def testTool(self):
- """Trying to think what to do for packages"""
- # The Reader interface is designed to work with single test entities,
- # either a string or the content of a text file (i.e., a single thing
- # that can be accessed via some sort of "read" method).
- # This doesn't work for packages, where one has multiple files.
- # Thus I suspect that the Reader interface is not appropriate for
- # what I want to do (at least, not without doing it unnecessary
- # violence and making it a lot more complicated).
- # So I need to do things "by hand"...
-
- source="# A Python comment"
- source_path="test.py"
-
- # Since a body of text is a Module, not a Package, we'll go straight
- # to it
- nodes = parse_module(source,source_path)
-
- # That then needs converting to a docutils tree
- document = make_document(nodes)
-
- # And *that* wants converting to the appropriate output format
-
- from docutils.writers.pseudoxml import Writer
- writer = Writer()
- writer.document = document
- writer.translate()
- actual_result = writer.output
-
- wanted_result = """\
-<document source="Module test">
- <section class="module" id="module-test" name="module test">
- <title>
- Module test\n"""
-
-
- if wanted_result != actual_result:
- print "+++++++++++++++++++++++++ WANT"
- print wanted_result
- print "+++++++++++++++++++++++++ GOT"
- print actual_result
- print "+++++++++++++++++++++++++"
-
- self.assertEqual(actual_result,wanted_result)
-
-
-def publish_string_with_traceback(reader=None,reader_name=None,
- parser_name=None,writer_name=None,
- source=None,source_path=None):
- """A modified version of publish_string, so I can request traceback.
- """
- from docutils.core import Publisher
- from docutils import io
- pub = Publisher(reader=reader,
- source_class=io.StringInput,
- destination_class=io.StringOutput)
- pub.set_components(reader_name="python",
- parser_name="restructuredtext",
- writer_name="pseudoxml")
-
- pub.process_command_line(argv=["--traceback"])
-
- pub.set_source(source=source, source_path=source_path)
- return pub.publish(enable_exit=False)
-
-
-if __name__ == "__main__":
- unittest.main()
diff --git a/sandbox/tibs/pysource2/transform.py b/sandbox/tibs/pysource2/transform.py
deleted file mode 100644
index 1be37bd02..000000000
--- a/sandbox/tibs/pysource2/transform.py
+++ /dev/null
@@ -1,157 +0,0 @@
-"""transform.py - create a docutils Document tree from a Package or Module tree
-
-:Author: Tibs
-:Contact: tibs@tibsnjoan.co.uk
-:Revision: $Revision$
-:Date: $Date$
-:Copyright: This module has been placed in the public domain.
-"""
-
-__docformat__ = 'reStructuredText'
-
-import os
-from docutils.utils import new_document
-import docutils.nodes as nodes
-from package import Package, NotPython
-from docutils.readers.python.moduleparser import Module, Class, Docstring
-
-def make_document(tree,settings=None):
- """Return a docutils Document tree constructed from this Python tree.
-
- The tree given must be either a Package or Module tree.
- """
-
- # @@@ Can it ever be anything other than a package or module?
- # I'd assert not - the module is the basic "smallest unit".
- # Should we test that?
- if isinstance(tree,Package):
- document = new_document("Package %s"%tree.filename,settings)
- section = make_package_section(tree)
- else:
- document = new_document("Module %s"%os.path.splitext(tree.filename)[0],
- settings)
- section = make_module_section(tree)
- document.append(section)
- return document
-
-def make_package_section(tree,parent_name=None):
- """Return a docutils tree constructed from this Package tree
- """
- if parent_name:
- tree_name = "%s.%s"%(parent_name,tree.filename)
- else:
- tree_name = tree.filename
- title = "Package %s"%(tree_name)
-
- # @@@ Do I really want to normalise (case fold, in particular)
- # the id/name for this section? Python names can legitimately
- # distinguish case, and whilst that's not terribly useful at
- # the file level (since not all OS/filesystems keep such a
- # distinction), it certainly is a valid possibility *within*
- # a file...
- #
- # make_id() produces a name that starts with [a-z] and continues
- # with a-z, 0-9 and hyphen (or something like that).
- #
- # fully_normalize_name() reduces spaces to single spaces (OK),
- # but also lowercases.
- #
- # @@@ Think more on usage here, I guess
- section = nodes.section(CLASS="package",id=nodes.make_id(title),
- name=nodes.fully_normalize_name(title))
- title = nodes.title(text=title)
- section.append(title)
-
- # @@@ I'm enforcing an order of modules before non-python files before
- # subpackages here
- # - do I really care?
- # - do I want some other way order?
- # - is this the best way to do it (e.g., I could sort the children
- # into order first instead)
- for child in tree.children:
- if isinstance(child,Module):
- subsection = make_module_section(child,tree_name)
- section.append(subsection)
- for child in tree.children:
- if isinstance(child,NotPython):
- subsection = make_not_python_section(child,tree_name)
- section.append(subsection)
- for child in tree.children:
- if isinstance(child,Package):
- subsection = make_package_section(child,tree_name)
- section.append(subsection)
- return section
-
-def make_module_section(tree,parent_name=None):
- """Return a docutils tree constructed from this Module sub-tree
- """
- module_name = os.path.splitext(tree.filename)[0]
- if parent_name:
- tree_name = "%s.%s"%(parent_name,module_name)
- else:
- tree_name = module_name
- title = "Module %s"%(tree_name)
-
- # @@@ Same considerations on id/name as above
- section = nodes.section(CLASS="module",id=nodes.make_id(title),
- name=nodes.fully_normalize_name(title))
- title = nodes.title(text=title)
- section.append(title)
-
- # Assume that the docstring must be the first child
- if len(tree.children) > 0 and \
- isinstance(tree.children[0],Docstring):
- section.append(make_docstring(tree.children[0]))
-
- # @@@ Again, I'm looking for classes before anything else
- for child in tree.children:
- if isinstance(child,Class):
- subsection = make_class_section(child,tree_name)
- section.append(subsection)
-
- return section
-
-def make_not_python_section(tree,parent_name=None):
- """Return a docutils tree constructed from this NotPython (file) sub-tree
- """
- if parent_name:
- tree_name = "%s.%s"%(parent_name,tree.filename)
- else:
- tree_name = tree.filename
- title = "File %s"%(tree_name)
-
- # @@@ Same considerations on id/name as above
- section = nodes.section(CLASS="file",id=nodes.make_id(title),
- name=nodes.fully_normalize_name(title))
- title = nodes.title(text=title)
- section.append(title)
- paragraph = nodes.paragraph(text="File ")
- paragraph.append(nodes.literal(text=tree.filename))
- paragraph.append(nodes.Text(" is not a Python module."))
- section.append(paragraph)
- return section
-
-def make_class_section(tree,parent_name):
- """Return a docutils tree constructed from this Class sub-tree
- """
- tree_name = "%s.%s"%(parent_name,tree.name)
- title = "Class %s"%(tree_name)
-
- # @@@ Same considerations on id/name as above
- section = nodes.section(CLASS="class",id=nodes.make_id(title),
- name=nodes.fully_normalize_name(title))
- title = nodes.title(text=title)
- section.append(title)
-
- # Assume that the docstring must be the first child
- if len(tree.children) > 0 and \
- isinstance(tree.children[0],Docstring):
- section.append(make_docstring(tree.children[0]))
-
- # @@@ Don't forget that we want base classes to be named at
- # some point
-
- return section
-
-def make_docstring(docstring):
- return nodes.literal_block(text=docstring.text,CLASS="docstring")
diff --git a/sandbox/tibs/pysource2/trivial_package/__init__.py b/sandbox/tibs/pysource2/trivial_package/__init__.py
deleted file mode 100644
index 3e664b315..000000000
--- a/sandbox/tibs/pysource2/trivial_package/__init__.py
+++ /dev/null
@@ -1,2 +0,0 @@
-"""A simple docstring.
-"""
diff --git a/sandbox/tibs/pysource2/trivial_package/file1.py b/sandbox/tibs/pysource2/trivial_package/file1.py
deleted file mode 100644
index 9636cb676..000000000
--- a/sandbox/tibs/pysource2/trivial_package/file1.py
+++ /dev/null
@@ -1,14 +0,0 @@
-#! /usr/bin/env python
-"""This is the first example file. It *does* use reStructuredText.
-"""
-
-__docformat__ = "reST"
-
-import os
-
-class Fred:
- """An example class - it announces each instance as it is created.
- """
-
- def __init__(self):
- print "Aha"
diff --git a/sandbox/tibs/pysource2/trivial_package/file2.py b/sandbox/tibs/pysource2/trivial_package/file2.py
deleted file mode 100644
index d0e203574..000000000
--- a/sandbox/tibs/pysource2/trivial_package/file2.py
+++ /dev/null
@@ -1,2 +0,0 @@
-"""This module is *not* using reStructuredText for its docstrings.
-"""
diff --git a/sandbox/tibs/pysource2/trivial_package/not_python b/sandbox/tibs/pysource2/trivial_package/not_python
deleted file mode 100644
index b447bba55..000000000
--- a/sandbox/tibs/pysource2/trivial_package/not_python
+++ /dev/null
@@ -1,3 +0,0 @@
-The content of this file is not Python.
-
-(Although it *is*, in fact, reStructuredText.)
diff --git a/sandbox/tibs/pysource2/trivial_package/sub_package/__init__.py b/sandbox/tibs/pysource2/trivial_package/sub_package/__init__.py
deleted file mode 100644
index e69de29bb..000000000
--- a/sandbox/tibs/pysource2/trivial_package/sub_package/__init__.py
+++ /dev/null