Changeset 853

Show
Ignore:
Timestamp:
09/18/05 02:33:28 (3 years ago)
Author:
rkern
Message:

notebook.py can now collate multiple sheets into one book through a DocBook? template (e.g. scipy_tutorial.xml)

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • nbdoc/trunk/notabene/docbook.py

    r851 r853  
    55import copy 
    66from cgi import escape 
     7import os 
     8import tempfile 
     9import subprocess 
    710 
    811from lxml import etree as ET 
     
    214217            return None 
    215218        return text.replace('\\', r'\\').replace('{', r'\{').replace('}', r'\}') 
    216     def prep_fo(self, tree): 
     219         
     220    @classmethod 
     221    def prep_fo(cls, tree): 
    217222        pass 
    218223 
    219     def prep_html(self, tree): 
     224    @classmethod 
     225    def prep_html(cls, tree): 
    220226        pass 
    221  
    222     def prep_latex(self, tree): 
     227     
     228    @classmethod 
     229    def prep_latex(cls, tree): 
    223230        listings = tree.xpath('//programlisting')  
    224231        for listing in listings:   
    225             listing.text = self.escape_latex(listing.text)   
     232            listing.text = cls.escape_latex(listing.text)   
    226233            for sub in listing.getiterator():   
    227                 sub.text = self.escape_latex(sub.text) 
    228                 sub.tail = self.escape_latex(sub.tail)   
    229  
    230     def to_formatted(self, sheet, kind='html', style=None): 
    231         """Convert a sheet to the desired output format. 
     234                sub.text = cls.escape_latex(sub.text) 
     235                sub.tail = cls.escape_latex(sub.tail)   
     236 
     237    @classmethod 
     238    def to_formatted(cls, dbxml, kind='html', style=None): 
     239        """Convert a DocBook document to the final format. 
    232240 
    233241        Returns a string containing the new document. 
     
    237245        xsl = getattr(style, '%s_xsl'%kind)() 
    238246        xslt = ET.XSLT(xsl) 
    239         article_tree = ET.ElementTree(self.transform_sheet(sheet)) 
    240         getattr(self, 'prep_%s' % kind)(article_tree) 
    241         newtree = xslt.apply(article_tree) 
     247        if ET.iselement(dbxml): 
     248            dbxml = ET.ElementTree(dbxml) 
     249        getattr(cls, 'prep_%s' % kind)(dbxml) 
     250        newtree = xslt.apply(dbxml) 
    242251        return xslt.tostring(newtree) 
    243252 
    244     def to_book(self, sheets, template=None, kind='html', style=None): 
    245         """Convert a list of sheets to a book with each sheet being a chapter. 
    246         """ 
    247         if style is None: 
    248             from notabene.styles import LightBGStyle as style 
    249         xsl = getattr(style, '%s_xsl' % kind)() 
    250         xslt = ET.XSLT(xsl) 
    251         if template is None: 
    252             book = ET.Element('book') 
     253    @classmethod 
     254    def write_formatted(cls, dbxml, name, format='html'): 
     255        """Convert DocBook document to the format and write it to disk. 
     256         
     257        This method will also run any post-processing necessary (e.g. pdflatex  
     258        to get PDF from LaTeX). 
     259         
     260        Return the filename that was created. 
     261        """ 
     262        extensions = {'latex': '.tex', 
     263                      'html': '.html', 
     264                      'doshtml': '.htm', #to allow specifying it explicitly 
     265                      'pdf': '.pdf', 
     266                      } 
     267 
     268        base, ext = os.path.splitext(name) #allows giving also ext in name 
     269        if ext not in extensions.values(): 
     270            #probably the name has a dot in it, like 'tut-2.3.5-db' 
     271            base = name 
     272            ext = False 
     273 
     274        if not ext: 
     275            ext = extensions.get(format, '.'+format) 
     276 
     277        filename = os.path.abspath(base + ext) 
     278        #could check if the given extension makes sense for the format 
     279 
     280        toPDF = False 
     281        if format == 'pdf': 
     282            format = 'latex' #we get pdf via latex for now 
     283            toPDF = True 
     284             
     285        doc = cls.to_formatted(dbxml, kind=format).encode('utf-8') 
     286 
     287        if toPDF: 
     288            env = os.environ.copy() 
     289            tmpfid, tmpfn = tempfile.mkstemp(suffix='.tex') 
     290            tmpf = os.fdopen(tmpfid, 'w+b') 
     291            try: 
     292                tmpf.write(doc) 
     293            finally: 
     294                tmpf.close() 
     295            try: 
     296                # Try as hard as we can to output the PDF in the same directory 
     297                # as the notebook file. 
     298                dir, fn = os.path.split(filename) 
     299                base = os.path.splitext(fn)[0] 
     300 
     301                # Abusing TEXMFOUTPUT like this is a hideous hack that we need 
     302                # to use for compatibility with teTeX < 3.0 and other older TeX 
     303                # distributions. pdflatex only recently grew a nice 
     304                # -output-directory option. This current strategy might be 
     305                # unreliable; TEXMFOUTPUT only kicks in when "the current 
     306                # directory is unwritable." We try to force that condition by 
     307                # giving the full pathname as the jobname. That works on OS X at 
     308                # least. 
     309                env['TEXMFOUTPUT'] = dir 
     310 
     311                #args = ['pdflatex', '-output-directory=%s'%dir, '-jobname=%s'%base] 
     312                args = ['pdflatex', '-jobname=%s'%os.path.join(dir,base)] 
     313                p = subprocess.Popen(args+[tmpfn], env=env) 
     314                p.wait() 
     315                # Do it a second time to make sure the references are right. 
     316                p = subprocess.Popen(args+[tmpfn], env=env) 
     317                p.wait() 
     318            finally: 
     319                os.unlink(tmpfn) 
     320 
     321            return filename 
     322 
    253323        else: 
    254             book = copy.deepcopy(template) 
    255         for sheet in sheets: 
    256             chapter = self.transform_sheet(sheet) 
    257             chapter.tag = 'chapter' 
    258             book.append(chapter) 
    259         book = ET.ElementTree(book) 
    260         getattr(self, 'prep_%s' % kind)(article_tree) 
    261         newtree = xslt.apply(article_tree) 
    262         return xslt.tostring(newtree) 
    263  
    264  
     324            f = open(filename, 'wb') 
     325            f.write(doc) 
     326            f.close() 
     327            return filename 
     328     
  • nbdoc/trunk/notabene/notebook.py

    r851 r853  
    22 
    33import os 
    4 import subprocess 
    5 import tempfile 
    64import warnings 
    75 
     
    108from notabene import normal 
    119from notabene import validate 
    12 from notabene.xmlutils import rdf, dc 
     10from notabene.xmlutils import nsmap, rdf, dc, xlink 
    1311 
    1412class SubelemWrapper(object): 
     
    448446    contents = property(get_contents) 
    449447 
     448    def write_formatted(self, filename=None, format='html'): 
     449        from notabene.docbook import DBFormatter 
     450        dbf = DBFormatter(self) 
     451        if filename is None: 
     452            base = self.name 
     453        else: 
     454            base = os.path.splitext(filename)[0] 
     455        sheet = self.root.find('sheet') 
     456        if sheet is not None: 
     457            dbxml = dbf.transform_sheet(sheet) 
     458            newfile = dbf.write_formatted(dbxml, base, format) 
     459            return newfile 
     460             
     461def spliturl(basedir, url): 
     462    import urlparse 
     463    parts = urlparse.urlparse(url) 
     464    if parts[0] not in ('file', ''): 
     465        warnings.warn('Unknown protocol %s://' % parts[0]) 
     466    path = parts[2] 
     467    frag = parts[-1] 
     468    path = os.path.abspath(os.path.join(basedir, path)) 
     469    return path, frag 
     470 
     471def book2docbook(bookfilename): 
     472    from notabene.docbook import DBFormatter 
     473    book = ET.parse(bookfilename) 
     474    basedir, basename = os.path.split(bookfilename) 
     475    child2parent = dict((c,p) for p in book.getiterator() for c in p) 
     476    for link in book.xpath('//*[@xlink:type="simple"]',  
     477        namespaces=nsmap(xlink)): 
     478        parent = child2parent[link] 
     479        path, frag = spliturl(basedir, link.get(xlink.href)) 
     480        print path, frag 
     481        nb = Notebook.from_file(path) 
     482        sheet = nb.xpath.evaluate('/notebook/sheet[@id="%s"]' % frag) 
     483        if sheet == []: 
     484            raise ValueError('could not find <sheet id="%s"> in %s' % 
     485                (frag, path)) 
     486        else: 
     487            sheet = sheet[0] 
     488        dbf = DBFormatter(nb) 
     489        dbxml = dbf.transform_sheet(sheet, nodetype=link.tag) 
     490        idx = parent.index(link) 
     491        parent[idx] = dbxml 
     492    return book 
     493 
    450494def main(): 
    451495    import sys 
     
    470514 
    471515    else: 
     516        from notabene.docbook import DBFormatter 
    472517        if options.book is None: 
    473518            for filename in args: 
    474                 base = os.path.splitext(filename)[0] 
    475519                nb = Notebook.from_file(filename) 
    476                 newfile = nb.write_formatted(base, options.format) 
    477                 print "%s -> %s" % (filename, newfile) 
    478         else: 
    479             raise NotImplementedError("XXX: need to figure this out") 
    480             sheets = [] 
    481             for filename in args: 
    482                 base = os.path.splitext(filename)[0] 
    483                 nb = Notebook.from_file(filename) 
     520                newfile = nb.write_formatted(filename, options.format) 
     521                if newfile is not None: 
     522                    print "%s -> %s" % (filename, newfile) 
     523                else: 
     524                    print 'No sheet in %s . Skipping.' % filename 
     525        else: 
     526            dbxml = book2docbook(options.book) 
     527            base = os.path.splitext(options.book)[0] 
     528            newfile = DBFormatter.write_formatted(dbxml, base, options.format) 
     529            print "%s -> %s" % (options.book, newfile) 
    484530                 
    485531 
  • nbdoc/trunk/notabene/xmlutils.py

    r827 r853  
     1#***************************************************************************** 
     2#       Copyright (C) 2005 Robert Kern. All rights reserved. 
     3# 
     4#  Distributed under the terms of the BSD License.  The full license is in 
     5#  the file COPYING, distributed as part of this software. 
     6#***************************************************************************** 
     7 
    18class XMLNS(object): 
    29    """Convenience object for handling namespaced tag names in ElementTree-like 
     
    4249dc = XMLNS('dc', 'http://purl.org/dc/elements/1.1/') 
    4350xsl = XMLNS('xsl', 'http://www.w3.org/1999/XSL/Transform') 
     51xlink = XMLNS('xlink', 'http://www.w3.org/1999/xlink') 
  • nbdoc/trunk/scipy_tutorial/chapter04.pybk

    r845 r853  
    113113integrals are actually functions which can be constant functions. An example of 
    114114using double integration to compute several values of 
    115 <ipython-inlineequation>I_{n}<ipython-inlineequation> is shown below: 
     115<ipython-inlineequation>I_{n}</ipython-inlineequation> is shown below: 
    116116</para> 
    117117<para>XXX: ipython 
  • nbdoc/trunk/scipy_tutorial/chapter10.pybk

    r845 r853  
    2020just convenient short-hand for Matrix.Matrix. If you are going to be doing a lot 
    2121of matrix-math, it is convenient to convert arrays into matrices using this 
    22 command. One convencience of using the mat command is that you can enter 
     22command. One convenience of using the mat command is that you can enter 
    2323two-dimensional matrices using MATLAB-like syntax with commas or spaces 
    24 separating columns and semicolons separting rows as long as the matrix is placed 
     24separating columns and semicolons separqting rows as long as the matrix is placed 
    2525in a string passed to mat.  
    2626</para> 
     
    3131<section> 
    3232<title>Finding Inverse</title> 
    33 <para>The inverse of a matrix \mathbf{A} is the matrix \mathbf{B} such that 
    34 \mathbf{AB}=\mathbf{I} where \mathbf{I} is the identity matrix consisting of 
    35 ones down the main diagonal. Usually \mathbf{B} is denoted 
    36 \mathbf{B}=\mathbf{A}^{-1}. In SciPy, the matrix inverse of the Numeric array, 
    37 A, is obtained using linalg.inv(A), or using A.I if A is a Matrix. For example, 
    38 let \mathbf{A=}\left[\begin{array}{ccc} 
     33<para>The inverse of a matrix <ipython-inlineequation>\mathbf{A}</ipython-inlineequation> is the matrix <ipython-inlineequation>\mathbf{B}</ipython-inlineequation> such that 
     34<ipython-inlineequation>\mathbf{AB}=\mathbf{I}</ipython-inlineequation> where <ipython-inlineequation>\mathbf{I}</ipython-inlineequation> is the identity matrix consisting of 
     35ones down the main diagonal. Usually <ipython-inlineequation>\mathbf{B}</ipython-inlineequation> is denoted 
     36<ipython-inlineequation>\mathbf{B}=\mathbf{A}^{-1}</ipython-inlineequation>. In SciPy, the matrix inverse of the Numeric array, 
     37A, is obtained using <code>linalg.inv(A)</code>, or using <code>A.I</code> if A is a Matrix. For example, 
     38let  
     39<ipython-equation>\mathbf{A=}\left[\begin{array}{ccc} 
    39401 &amp; 3 &amp; 5\\ 
    40412 &amp; 5 &amp; 1\\ 
     
    4546-1.48 &amp; 0.36 &amp; 0.88\\ 
    46470.56 &amp; 0.08 &amp; -0.36\\ 
    47 0.16 &amp; -0.12 &amp; 0.04\end{array}\right].} The following example demonstrates this computation in SciPy 
     480.16 &amp; -0.12 &amp; 0.04\end{array}\right].} 
     49</ipython-equation> 
     50 The following example demonstrates this computation in SciPy 
    4851</para> 
    4952<para> XXX: ipython 
     
    7174matrix is offered which can speed up the processing when applicable. As an 
    7275example, suppose it is desired to solve the following simultaneous equations: 
    73 x+3y+5z We could find the solution vector using a matrix inverse: 
     76<ipython-equation verb="1"> 
     77   \begin{eqnarray*} 
     78   x+3y+5z &amp; = &amp; 10\\ 
     79   2x+5y+z &amp; = &amp; 8\\ 
     80   2x+3y+8z &amp; = &amp; 3\end{eqnarray*} 
     81</ipython-equation> 
     82 We could find the solution vector using a matrix inverse: 
     83<ipython-equation> 
    7484\left[\begin{array}{c} 
    7585x\\ 
     
    8797-9.28\\ 
    88985.16\\ 
    89 0.76\end{array}\right]. However, it is better to use the linalg.solve command 
     990.76\end{array}\right]. 
     100</ipython-equation> 
     101However, it is better to use the linalg.solve command 
    90102which can be faster and more numerically stable. In this case it gives the same 
    91103answer as shown in the following example:  
  • nbdoc/trunk/scipy_tutorial/chapter12.pybk

    r844 r853  
    1212</para> 
    1313<itemizedlist> 
    14 <listitem><para>* fromimage --- convert a PIL image to a Numeric array 
     14<listitem><para>fromimage --- convert a PIL image to a Numeric array 
    1515</para></listitem> 
    16 <listitem><para>* toimage --- convert Numeric array to PIL image 
     16<listitem><para>toimage --- convert Numeric array to PIL image 
    1717</para></listitem> 
    18 <listitem><para>* imsave --- save Numeric array to an image file 
     18<listitem><para>imsave --- save Numeric array to an image file 
    1919</para></listitem> 
    20 <listitem><para>* imread --- read an image file into a Numeric array 
     20<listitem><para>imread --- read an image file into a Numeric array 
    2121</para></listitem> 
    22 <listitem><para>* imrotate --- rotate an image (a Numeric array) counter-clockwise 
     22<listitem><para>imrotate --- rotate an image (a Numeric array) counter-clockwise 
    2323</para></listitem> 
    24 <listitem><para>* imresize --- resize an image using the PIL 
     24<listitem><para>imresize --- resize an image using the PIL 
    2525</para></listitem> 
    26 <listitem><para>* imshow --- external viewer of a Numeric array (using PIL) 
     26<listitem><para>imshow --- external viewer of a Numeric array (using PIL) 
    2727</para></listitem> 
    28 <listitem><para>* imfilter --- fast, simple built-in filters provided by PIL 
     28<listitem><para>imfilter --- fast, simple built-in filters provided by PIL 
    2929</para></listitem> 
    30 <listitem><para>* radon --- simple radon transform based on imrotate 
     30<listitem><para>radon --- simple radon transform based on imrotate 
    3131</para></listitem> 
    3232</itemizedlist>