<?xml version="1.0" encoding="UTF-8"?>

<rss version="2.0"
     xmlns:content="http://purl.org/rss/1.0/modules/content/"
     xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
     xmlns:atom="http://www.w3.org/2005/Atom"
     xmlns:dc="http://purl.org/dc/elements/1.1/"
     xmlns:wfw="http://wellformedweb.org/CommentAPI/"
     >
  <channel>
    <atom:link href="http://kitchingroup.cheme.cmu.edu/blog/feed/index.xml" rel="self" type="application/rss+xml" />
    <title>The Kitchin Research Group</title>
    <link>https://kitchingroup.cheme.cmu.edu/blog</link>
    <description>Chemical Engineering at Carnegie Mellon University</description>
    <pubDate>Sat, 01 Nov 2025 13:47:46 GMT</pubDate>
    <generator>Blogofile</generator>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    
    <item>
      <title>Literate programming with python doctests</title>
      <link>https://kitchingroup.cheme.cmu.edu/blog/2018/05/17/Literate-programming-with-python-doctests</link>
      <pubDate>Thu, 17 May 2018 16:41:19 EDT</pubDate>
      <category><![CDATA[orgmode]]></category>
      <category><![CDATA[noweb]]></category>
      <category><![CDATA[python]]></category>
      <guid isPermaLink="false">LOCS3-CpseSjnbubGeO3Zmhf9Rc=</guid>
      <description>Literate programming with python doctests</description>
      <content:encoded><![CDATA[


&lt;div id="table-of-contents"&gt;
&lt;h2&gt;Table of Contents&lt;/h2&gt;
&lt;div id="text-table-of-contents"&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#org91f890f"&gt;1. Add a way to run the tests&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#org4759a84"&gt;2. Tangle the file&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#org8727607"&gt;3. Run the tests&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#org5a82a2f"&gt;4. The noweb doctest block&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
On the org-mode mailing list we had a nice discussion about using noweb and org-mode in literate programming. The results of that discussion were blogged about &lt;a href="http://kdr2.com/tech/emacs/1805-approach-org-ref-code-to-text.html"&gt;here&lt;/a&gt;. I thought of a different application of this for making &lt;a href="https://pymotw.com/3/doctest/"&gt;doctests&lt;/a&gt; in Python functions. I have to confess I have never liked these because I have always thought they were a pain to write since you basically have to put code and results into a docstring. The ideas developed in the discussion above led me to think of a new way to write these that seems totally reasonable.
&lt;/p&gt;

&lt;p&gt;
The idea is just to put noweb placeholders in the function docstring for the doctests. The placeholders will be expanded when you tangle the file, and they will get their contents from other src-blocks where you have written and run examples to test them.
&lt;/p&gt;

&lt;p&gt;
This video might make the rest of this post easier to follow:
&lt;/p&gt;
&lt;iframe width="560" height="315" src="https://www.youtube.com/embed/u8CWbedVV9Y" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen&gt;&lt;/iframe&gt;

&lt;p&gt;
I will illustrate the idea using org-mode and the ob-ipython I have in scimax. The defaults of my ob-ipython setup are not useful for this example because it puts the execution count and mime types of output in the output. These are not observed in a REPL, and so we turn this off by setting these variables.
&lt;/p&gt;

&lt;div class="org-src-container"&gt;
&lt;pre class="src src-emacs-lisp"&gt;(&lt;span style="color: #0000FF;"&gt;setq&lt;/span&gt; ob-ipython-suppress-execution-count t
      ob-ipython-show-mime-types nil)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
Now, we make an example function that takes a single argument and returns one divided by that argument. This block is runnable, and the function is then defined in the jupyter kernel. The docstring contains several noweb references to doctest blocks we define later. For now, they don't do anything. See &lt;a href="#org5a82a2f"&gt;The noweb doctest block&lt;/a&gt; section for the block that is used to expand these. This block also has a tangle header which indicates the file to tangle the results to. When I run this block, it is sent to a Jupyter kernel and saved in memory for use in subsequent blocks.
&lt;/p&gt;

&lt;p&gt;
Here is the block with no noweb expansion. Note that this is easier to read in the original org source than it is to read in the published blog format.
&lt;/p&gt;

&lt;div class="org-src-container"&gt;
&lt;pre class="src src-ipython"&gt;&lt;span style="color: #0000FF;"&gt;def&lt;/span&gt; &lt;span style="color: #006699;"&gt;func&lt;/span&gt;(a):
&lt;span style="color: #9B9B9B; background-color: #EDEDED;"&gt; &lt;/span&gt;   &lt;span style="color: #036A07;"&gt;"""A function to divide one by a.&lt;/span&gt;

&lt;span style="color: #9B9B9B; background-color: #EDEDED;"&gt; &lt;/span&gt;&lt;span style="color: #036A07;"&gt;   &amp;lt;&amp;lt;doctest("doctest-1")&amp;gt;&amp;gt;&lt;/span&gt;

&lt;span style="color: #9B9B9B; background-color: #EDEDED;"&gt; &lt;/span&gt;&lt;span style="color: #036A07;"&gt;   &amp;lt;&amp;lt;doctest("doctest-2")&amp;gt;&amp;gt;&lt;/span&gt;

&lt;span style="color: #9B9B9B; background-color: #EDEDED;"&gt; &lt;/span&gt;&lt;span style="color: #036A07;"&gt;   &amp;lt;&amp;lt;doctest("doctest-3")&amp;gt;&amp;gt;&lt;/span&gt;

&lt;span style="color: #9B9B9B; background-color: #EDEDED;"&gt; &lt;/span&gt;&lt;span style="color: #036A07;"&gt;   Returns: 1 / a.&lt;/span&gt;
&lt;span style="color: #9B9B9B; background-color: #EDEDED;"&gt; &lt;/span&gt;&lt;span style="color: #036A07;"&gt;   """&lt;/span&gt;
&lt;span style="color: #9B9B9B; background-color: #EDEDED;"&gt; &lt;/span&gt;   &lt;span style="color: #0000FF;"&gt;return&lt;/span&gt; 1 / a

&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
Now, we can write a series of named blocks that define various tests we might want to use as doctests. You can run these blocks here, and verify they are correct. Later, when we tangle the document, these will be incorporated into the tangled file in the docstring we defined above.
&lt;/p&gt;

&lt;div class="org-src-container"&gt;
&lt;pre class="src src-ipython" id="org4eaeeaf"&gt;func(5) == 0.2
&lt;/pre&gt;
&lt;/div&gt;

&lt;pre class="example"&gt;
True

&lt;/pre&gt;



&lt;p&gt;
This next test will raise an Exception, and we just run it to make sure it does.
&lt;/p&gt;

&lt;div class="org-src-container"&gt;
&lt;pre class="src src-ipython" id="org560fcaf"&gt;func(0)
&lt;/pre&gt;
&lt;/div&gt;

&lt;pre class="example"&gt;

ZeroDivisionErrorTraceback (most recent call last)
&amp;lt;ipython-input-6-ba0cd5a88f0a&amp;gt; in &amp;lt;module&amp;gt;()
----&amp;gt; 1 func(0)

&amp;lt;ipython-input-1-eafd354a3163&amp;gt; in func(a)
     18     Returns: 1 / a.
     19     """
---&amp;gt; 20     return 1 / a

ZeroDivisionError: division by zero

&lt;/pre&gt;



&lt;p&gt;
This is just a doctest with indentation to show how it is used.
&lt;/p&gt;

&lt;div class="org-src-container"&gt;
&lt;pre class="src src-ipython" id="org968debf"&gt;&lt;span style="color: #0000FF;"&gt;for&lt;/span&gt; i &lt;span style="color: #0000FF;"&gt;in&lt;/span&gt; &lt;span style="color: #006FE0;"&gt;range&lt;/span&gt;(1, 4):
&lt;span style="color: #9B9B9B; background-color: #EDEDED;"&gt; &lt;/span&gt;   &lt;span style="color: #0000FF;"&gt;print&lt;/span&gt;(func(i))
&lt;/pre&gt;
&lt;/div&gt;

&lt;pre class="example"&gt;
1.0
0.5
0.3333333333333333


&lt;/pre&gt;



&lt;p&gt;
That concludes the examples I want incorporated into the doctests. Each one of these blocks has a name, which is used as an argument to the noweb references in the function docstring.
&lt;/p&gt;

&lt;div id="outline-container-org91f890f" class="outline-2"&gt;
&lt;h2 id="org91f890f"&gt;&lt;span class="section-number-2"&gt;1&lt;/span&gt; Add a way to run the tests&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-1"&gt;
&lt;p&gt;
This is a common idiom to enable easy running of the doctests. This will get tangled out to the file.
&lt;/p&gt;

&lt;div class="org-src-container"&gt;
&lt;pre class="src src-ipython"&gt;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt; &lt;span style="color: #006FE0;"&gt;__name__&lt;/span&gt; == &lt;span style="color: #008000;"&gt;"__main__"&lt;/span&gt;:
&lt;span style="color: #9B9B9B; background-color: #EDEDED;"&gt; &lt;/span&gt;   &lt;span style="color: #0000FF;"&gt;import&lt;/span&gt; doctest
&lt;span style="color: #9B9B9B; background-color: #EDEDED;"&gt; &lt;/span&gt;   doctest.testmod()
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;


&lt;div id="outline-container-org4759a84" class="outline-2"&gt;
&lt;h2 id="org4759a84"&gt;&lt;span class="section-number-2"&gt;2&lt;/span&gt; Tangle the file&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-2"&gt;
&lt;p&gt;
So far, the Python code we have written only exists in the org-file, and in memory. Tangling is the extraction of the code into a code file.
&lt;/p&gt;

&lt;p&gt;
We run this command, which extracts the code blocks marked for tangling, and expands the noweb references in them.
&lt;/p&gt;

&lt;div class="org-src-container"&gt;
&lt;pre class="src src-emacs-lisp"&gt;(org-babel-tangle)
&lt;/pre&gt;
&lt;/div&gt;

&lt;table border="2" cellspacing="0" cellpadding="6" rules="groups" frame="hsides"&gt;


&lt;colgroup&gt;
&lt;col  class="org-left" /&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class="org-left"&gt;test.py&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;
Here is what we get:
&lt;/p&gt;

&lt;pre class="example"&gt;
def func(a):
    """A function to divide one by a.

    &amp;gt;&amp;gt;&amp;gt; func(5) == 0.2
    True

    &amp;gt;&amp;gt;&amp;gt; func(0)
    Traceback (most recent call last):
    ZeroDivisionError: division by zero

    &amp;gt;&amp;gt;&amp;gt; for i in range(1, 4):
    ...     print(func(i))
    1.0
    0.5
    0.3333333333333333


    Returns: 1 / a.
    """
    return 1 / a

if __name__ == "__main__":
    import doctest
    doctest.testmod()

&lt;/pre&gt;

&lt;p&gt;
That looks like a reasonable python file. You can see the doctest blocks have been inserted into the docstring, as desired. The proof of course is that we can run these doctests, and use the python module. We show that next.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;


&lt;div id="outline-container-org8727607" class="outline-2"&gt;
&lt;h2 id="org8727607"&gt;&lt;span class="section-number-2"&gt;3&lt;/span&gt; Run the tests&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-3"&gt;
&lt;p&gt;
Now, we can check if the tests pass in a fresh run (i.e. not using the version stored in the jupyter kernel.) The standard way to run the doctests is like this:
&lt;/p&gt;

&lt;div class="org-src-container"&gt;
&lt;pre class="src src-sh"&gt;python test.py -v
&lt;/pre&gt;
&lt;/div&gt;




&lt;p&gt;
Well, that's it! It worked fine. Now we have a python file we can import and reuse, with some doctests that show how it works. For example, here it is in a small Python script.
&lt;/p&gt;

&lt;div class="org-src-container"&gt;
&lt;pre class="src src-python"&gt;&lt;span style="color: #0000FF;"&gt;from&lt;/span&gt; test &lt;span style="color: #0000FF;"&gt;import&lt;/span&gt; func
&lt;span style="color: #0000FF;"&gt;print&lt;/span&gt;(func(3))
&lt;/pre&gt;
&lt;/div&gt;

&lt;pre class="example"&gt;
0.3333333333333333

&lt;/pre&gt;



&lt;p&gt;
There are surely some caveats to keep in mind here. This was just a simple proof of concept idea that isn't tested beyond this example. I don't know how many complexities would arise from more complex doctests. But, it seems like a good idea to continue pursuing if you like using doctests, and like using org-mode and interactive/literate programming techniques.
&lt;/p&gt;

&lt;p&gt;
It is definitely an interesting way to use noweb to build up better code files in my opinion.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id="outline-container-org5a82a2f" class="outline-2"&gt;
&lt;h2 id="org5a82a2f"&gt;&lt;a id="ID-D4437A03-A9D0-4B6D-B254-5F03CFB25F95"&gt;&lt;/a&gt;&lt;span class="section-number-2"&gt;4&lt;/span&gt; The noweb doctest block&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-4"&gt;
&lt;p&gt;
These blocks are used in the noweb expansions. Each block takes a variable which is the name of a block. This block grabs the body of the named src block and formats it as if it was in a REPL.
&lt;/p&gt;

&lt;p&gt;
We also grab the results of the named block and format it for the doctest. We use a heuristic to detect Tracebacks and modify the output to be consistent with it. In that case we assume the relevant Traceback is on the last line.
&lt;/p&gt;

&lt;p&gt;
Admittedly, this does some fragile feeling things, like trimming whitespace here and there to remove blank lines, and quoting quotes (which was not actually used in this example), and removing the ": " pieces of ob-ipython results. Probably other ways of running the src-blocks would not be that suitable for this.
&lt;/p&gt;

&lt;div class="org-src-container"&gt;
&lt;pre class="src src-emacs-lisp" id="org52486c2"&gt;(org-babel-goto-named-src-block name)
(&lt;span style="color: #0000FF;"&gt;let*&lt;/span&gt; ((src (s-trim-right (org-element-property &lt;span style="color: #006FE0;"&gt;:value&lt;/span&gt; (org-element-context))))
       (src-lines (split-string src &lt;span style="color: #008000;"&gt;"\n"&lt;/span&gt;))
       body result)
  (&lt;span style="color: #0000FF;"&gt;setq&lt;/span&gt; body
        (s-trim-right
         (s-concat &lt;span style="color: #008000;"&gt;"&amp;gt;&amp;gt;&amp;gt; "&lt;/span&gt; (car src-lines) &lt;span style="color: #008000;"&gt;"\n"&lt;/span&gt;
                   (s-join &lt;span style="color: #008000;"&gt;"\n"&lt;/span&gt; (mapcar (&lt;span style="color: #0000FF;"&gt;lambda&lt;/span&gt; (s)
                                          (concat &lt;span style="color: #008000;"&gt;"... "&lt;/span&gt; s))
                                        (cdr src-lines))))))
  &lt;span style="color: #8D8D84;"&gt;;; &lt;/span&gt;&lt;span style="color: #8D8D84; font-style: italic;"&gt;now the results&lt;/span&gt;
  (org-babel-goto-named-result name)
  (&lt;span style="color: #0000FF;"&gt;let&lt;/span&gt; ((result (org-element-context)))
    (&lt;span style="color: #0000FF;"&gt;setq&lt;/span&gt; result
          (&lt;span style="color: #0000FF;"&gt;thread-last&lt;/span&gt;
              (buffer-substring (org-element-property &lt;span style="color: #006FE0;"&gt;:contents-begin&lt;/span&gt; result)
                                (org-element-property &lt;span style="color: #006FE0;"&gt;:contents-end&lt;/span&gt; result))
            (s-trim)
            &lt;span style="color: #8D8D84;"&gt;;; &lt;/span&gt;&lt;span style="color: #8D8D84; font-style: italic;"&gt;remove ": " from beginning of lines&lt;/span&gt;
            (replace-regexp-in-string &lt;span style="color: #008000;"&gt;"^: *"&lt;/span&gt; &lt;span style="color: #008000;"&gt;""&lt;/span&gt;)
            &lt;span style="color: #8D8D84;"&gt;;; &lt;/span&gt;&lt;span style="color: #8D8D84; font-style: italic;"&gt;quote quotes&lt;/span&gt;
            (replace-regexp-in-string &lt;span style="color: #008000;"&gt;"\\\""&lt;/span&gt; &lt;span style="color: #008000;"&gt;"\\\\\""&lt;/span&gt;)))
    (&lt;span style="color: #0000FF;"&gt;when&lt;/span&gt; (string-match &lt;span style="color: #008000;"&gt;"Traceback"&lt;/span&gt; result)
      (&lt;span style="color: #0000FF;"&gt;setq&lt;/span&gt; result (format
                    &lt;span style="color: #008000;"&gt;"Traceback (most recent call last):\n%s"&lt;/span&gt;
                    (car (last (split-string result &lt;span style="color: #008000;"&gt;"\n"&lt;/span&gt;))))))
    (concat body &lt;span style="color: #008000;"&gt;"\n"&lt;/span&gt; result)))
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Copyright (C) 2018 by John Kitchin. See the &lt;a href="/copying.html"&gt;License&lt;/a&gt; for information about copying.&lt;p&gt;
&lt;p&gt;&lt;a href="/org/2018/05/17/Literate-programming-with-python-doctests.org"&gt;org-mode source&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Org-mode version = 9.1.13&lt;/p&gt;]]></content:encoded>
    </item>
  </channel>
</rss>
