Backing up your email

Just in case someone might find this useful …

I recently had something bad happen to me. I use Thunderbird (on Windows Vista) as my email client. I asked Thunderbird to compact my email files, and it wiped out a bunch of my email messages. (I think that one of my email files must have been corrupt, and when I compacted it, the compaction process wiped out messages that should not have been wiped out.)

You can recover deleted email messages … but not after the email file has been compacted. So the messages were not recoverable. Bummer.

The upside is that this nasty incident led me to learn some things.

One thing that I learned was that the disk backup utility that I was using at the time did NOT backup my email files. The email files were stored in a directory called AppData, and the AppData directory is a “hidden” directory. So the backup utility didn’t see the AppData directory, and didn’t back it up. So I had no backup of the deleted messages.

Learning that led me to investigate ways to backup my email files, and I found this: Five ways to keep your emails backed up

For backing up Thunderbird files, it recommends MozBackup as being fast, free and easy to use. So I tried MozBackup, and those claims seem to be true.

Now I’m evaluating different disk backup options.

The take-away here is that you need to pay special attention to backing up your email files. So if you’re not backing up your email files, take a look at Five ways to keep your emails backed up (and read the comments, which are useful) or google something like “email backup”.

[Note that this applies only if you are using an email client such as Thunderbird, Outlook, Outlook Express, etc. If you don't use an email client, and do all of your email work through a Web interface to your Internet Service Provider, then this is not an issue.]

How to post source code on WordPress

This post is for folks who blog about Python (or any programming language for that matter) on WordPress.
Updated 2011-11-09 to make it easier to copy-and-paste the [sourcecode] template.

My topic today is How to post source code on WordPress.

The trick is to use the WordPress [sourcecode] shortcut tag, as documented at http://en.support.wordpress.com/code/posting-source-code/.

Note that when the WordPress docs tell you to enclose the [sourcecode] shortcut tag in square — not pointy — brackets, they mean it. When you view your post as HTML, what you should see is square brackets around the shortcut tags, not pointy brackets.

Here is the tag I like to use for snippets of Python code.


[sourcecode language="python" wraplines="false" collapse="false"]
your source code goes here
[/sourcecode]


The default for wraplines is true, which causes long lines to be wrapped. That isn’t appropriate for Python, so I specify wraplines=”false”.

The default for collapse is false, which is what I normally want. But I code it explicitly, as a reminder that if I ever want to collapse a long code snippet, I can.


Here are some examples.

Note that

  • WordPress knows how to do syntax highlighting for Python. It uses Alex Gorbatchev’s SyntaxHighlighter.
  • If you hover your mouse pointer over the code, you get a pop-up toolbar that allows you to look at the original source code snippet, copy it to the clipboard, print it, etc.

(1)

First, a normal chunk of relatively short lines of Python code.

indentCount = 0
textChars = []
suffixChars = []

# convert the line into a list of characters
# and feed the list to the ReadAhead generator
chars = ReadAhead(list(line))

c = chars.next() # get first

while c and c == INDENT_CHAR:
    # process indent characters
    indentCount += 1
    c = chars.next()

while c and c != SYMBOL:
    # process text characters
    textChars.append(c)
    c = chars.next()

if c and c == SYMBOL:
    c = chars.next() # read past the SYMBOL
    while c:
        # process suffix characters
        suffixChars.append(c)
        c = chars.next()

(2)

Here is a different code snippet. This one has a line containing a very long comment. Note that the long line is NOT wrapped, and a horizontal scrollbar is available so that you can scroll as far to the right as you need to. That is because we have specified wraplines=”false”.

somePythonVariable = 1
# This is a long, single-line, comment.  I put it here to illustrate the effect of the wraplines argument.  In this code snippet, wraplines="false", so lines are NOT wrapped, but extend indefinitely, and a horizontal scrollbar is available so that you can scroll as far to the right as you need to.

(3)

This is what a similar code snippet would look like if we had specified wraplines=true. Note that line 2 wraps around and there is no horizontal scrollbar.

somePythonVariable = 1
# This is a long, single-line, comment.  I put it here to illustrate the effect of the wraplines argument.  In this code snippet, wraplines="true", so lines are ARE wrapped.  They do NOT extend indefinitely, and a horizontal scrollbar is NOT available so that you can scroll as far to the right as you need to.

(4)

Finally, the same code snippet with collapse=true, so the code snippet initially displays as collapsed. Clicking on the collapsed code snippet will cause it to expand.

somePythonVariable = 1
# This is a long, single-line, comment.  I put it here to illustrate the effect of the wraplines argument.  In this code snippet, wraplines="true", so lines are ARE wrapped.  They do NOT extend indefinitely, and a horizontal scrollbar is NOT available so that you can scroll as far to the right as you need to.

As far as I can tell, once a reader has expanded a snippet that was initially collapsed, there is no way for him to re-collapse it. That would be a nice enhancement for WordPress — to allow a reader to collapse and expand a code snippet.


Here is a final thought about wraplines. If you specify wraplines=”false”, and a reader prints a paper copy of your post, the printed output will not show the scrollbar, and it will show only the portion of long lines that were visible on the screen. In short, the printed output might cut off the right-hand part of long lines.

In most cases, I think, this should not be a problem. The pop-up tools allow a reader to view or print the entire source code snippet if he wants to. Still, I can imagine cases in which I might choose to specify wraplines=”true”, even for a whitespace-sensitive language such as Python. And I can understand that someone else, simply as a matter of personal taste, might prefer to specify wraplines=”true” all of the time.

Now that I think of it, another nice enhancement for WordPress would be to allow a reader to toggle wraplines on and off.


Keep on bloggin’!

PyCharm gotchas

I’ve been playing with PyCharm, the new Python IDE.  I like it a lot.  But I’ve discovered a few major gotchas.

I should note that I come from a Windows background, and I’m used to standard Windows keyboard shortcuts and editor behavior.  So what I’m going to describe may be standard behavior for editors on *nix, and nothing surprising to say, Ubuntu programmers.  But I’m working on Windows, and on Windows PyCharm’s out-of-the-box configuration of keyboard shortcuts is definitely a big gotcha.

First of all, on Windows ctl+z is the standard shortcut key for UNDO, and ctl+y is the standard shortcut key for REDO (or in some contexts, DO AGAIN).  But in the default PyCharm configuration, ctl+y is not REDO but DELETE LINE.  Imagine trying to REDO a series of commands by repeatedly punching ctl+y…  and watching your source code evaporate!  That was me, brother.

Second, on most Windows editors (and things like Netbeans and Eclipse, too) if you try to close a file that has unsaved changes, the editor will warn you and ask you what you want to do.  Not so PyCharm.  If you click on a tab to close a file (a file with unsaved changes), PyCharm saves the file and closes it.  No warnings. 

As I write this, I realize that I don’t know how to tell PyCharm to close a file without also writing it to disk.

Third, PyCharm offers several alternate keyboard shortcut configurations… but they all seem to be *nix inspired.  There is no pre-built alternate shortcut configuration for Windows-like behavior. 

On the upside, though, PyCharm provides a lot of support for  keyboard shortcut customization, and you can customize the keyboard shortcuts to the behavior that you want.  The PyCharm online documentation is good, and detailed.  Very well done.

Some time I might blog about what I like about PyCharm.  As I say, there is a lot to like about PyCharm and I don’t want to slam it.  But consider this a heads-up.

Command-line syntax: some basic concepts

I’ve been reading about parsers for command-line arguments lately, for example Plac. And, as Michele Simionato says:

There is no want of command line arguments parsers in the Python world. The standard library alone contains three different modules: getopt (from the stone age), optparse (from Python 2.3) and argparse (from Python 2.7).

My reading has made me realize that there is an immense range of possible syntaxes for command-line arguments, and far less consensus and standardization than I thought. Although there are some general styles that programmers often use when implementing the command-line arguments for their applications, basically every programmer is free to do whatever he (or she) wants. The result is that whenever you encounter an application for the first time, you can’t safely assume anything about the syntax of its command-line arguments.

It also has made me wonder if anyone had ever written an overview of, or introduction to, the basic concepts involved in command line arguments. I searched the Web without finding one, so I thought it would be interesting to try to write one.  I can live with the risk that I’m re-inventing the wheel.

Of course, there may be something out there and I just missed it. So if you know of some other discussion of this topic, please leave a comment and tell me about it. And if there is something that I missed here, I’d appreciate a comment about that too.

What is a command line argument?

When you invoke an application from a command line, it is often useful to be able to send one or more pieces of information from the command line to the application. As a simple example, we might want to start a text editor and also tell it the name of a file that it should open, like this

          superedit a_filename.txt

In this example, “superedit” is the name of the application, and “a_filename.txt” is a command line argument: in this case, the name of a file.

It is possible to supply more than one command line argument

We often want to send an application multiple arguments, like this:

          rename file_a.txt  file_b.txt

Positional arguments, named arguments, and flags

There are three types of command line argument: positional arguments, named arguments, and flags.

  • A positional argument is a bare value, and its position in a list of arguments identifies it.
  • A named argument is a (key, value) pair, where the key identifies the value.
  • A flag is a stand-alone key, whose presence or absence provides information to the application.

If we supplied the “rename” application with two positional arguments, like this

          rename file_a.txt  file_b.txt

then the position of the arguments identifies the value.

  • The value in position 1 (“file_a.txt”) is the current name of the file.
  • The value in position 2 (“file_b.txt”) is the requested new name of the file.

We could have written the “rename” application so that it requires two named arguments, like this

          rename  -oldname file_a.txt  -newname file_b.txt

A flag is an argument whose presence alone is enough to convey information to the application. A good example is the frequently-used “-v” or "--verbose" argument.

Although it is possible to think of flags as degenerate named arguments (named arguments that have a key but no value), I find it easier to think of flags as a distinct type of argument, different from named arguments.

Keyword arguments and options

I will use the term keyword argument to cover both named arguments and flags.

David Goodger notes (in the first comment on the first version of this post) that I am not using the traditional Unix command-line lexicon.  What I have called keyword arguments are — on Unix platforms — traditionally called options;  what I have called values are traditionally called option arguments; and what I have called positional arguments, the Open Group calls operands.  So I should probably say something about my choice of technical terminology.

For the purposes of this analysis, I prefer not to use the traditional Unix vocabulary of options, for a number of reason.  First of all, the term option tends to be Unix-specific; on Windows the term parameter is more frequently used.  Second, the investigation began with command-line parsers, and in the context of a discussion of parsers and parsing, keyword argument seems a more traditional and appropriate term than option.  Third, the usual definition of option is not very useful.

Arguments are options if they begin with a hyphen.

And finally, the term option implies optionality.  Whether an argument is optional or required is a semantic issue rather than a syntactical issue.  At this point I’m interested in syntactical issues, so I want to use a semantically neutral vocabulary.  We can talk about options and optionality later, when we look at semantic concepts.

Keyword arguments require a sigil

When keyword arguments are used, there must be some mechanism for distinguishing a key from a value or from a positional argument. That mechanism is a “sigil”: a special character or string of characters that indicates the beginning of a key. In our example, the sigil was a dash (a hyphen).

On Windows, the sigil is typically a forward slash: “/”.

On Unix-like operating systems, the sigil is typically a dash "-".

Some applications use multiple sigils.  With the plus sign “+” as a sigil, for instance, it is possible to use flags to turn options on and off.

          attrib   -readonly    -archive     file_A.txt
          attrib   +readonly    +archive     file_A.txt

Single-character and multi-character keys

Some applications, especially on Unix, make a distinction between single-character keys and multi-character keys (“long options”), with a single-dash sigil "-" indicating the beginning of a single-character key, and a double dash "--" sigil indicating the beginning of a multi-character key. Often, an application will support both single-character and multi-character keys for the same argument. For example, the “rename” application might accept both this

          rename  -o file_a.txt  -n file_b.txt

and this

          rename  --oldname file_a.txt  --newname file_b.txt

Fixed-length and variable-length keys

The previous section describes what I think most Unix programmers would say is the difference between single-dash and double-dash keys. But I think it is actually wrong.

The real difference between a single-dash sigil "-" and a double dash "--" sigil is not the difference between one and many, but the difference between fixed-length and variable-length keys. (This is obscured by the fact that a single-character key is also automatically a fixed-length key.)

The thing that really makes keys that begin with a single dash different from keys that begin with a double dash is not that they are one character long, but that their length is fixed and known. For example, flag concatenation (see below) is possible because the flag keys have a known and fixed length. It doesn’t depend on the flag keys being one character long — it would work just as well if the length for flag keys was fixed at two or even three characters. And this is also true of the third technique for distinguishing keys from argument values (see the next section).

Named arguments require a mechanism to distinguish keys from argument values

One technique is to use whitespace to separate argument values from keys. We saw this in our earlier example

          rename  -o file_a.txt  -n file_b.txt

A second technique is to use a special (non-whitespace) character to separate argument values from keys. This special character could be any character that cannot occur in either the key or argument value.

On Unix, this is traditionally an equal sign “=”, like this.

          rename  -o=file_a.txt  -n=file_b.txt

On Windows and MS-DOS this is traditionally a colon “:”, like this.

          rename  /o:file_a.txt  /n:file_b.txt

An application might permit whitespace before and after the equal sign, like this.

          rename  -o = file_a.txt  -n = file_b.txt

A third technique is to use the known length of the key to distinguish the key from the argument value. Suppose the “rename” application uses only 1-character keys. Then it might accept arguments like this.

          rename  -ofile_a.txt  -nfile_b.txt

Fixed-length keys make flag concatenation possible

Suppose that an application follows the convention that a single-dash sigil signals the start of a single-character flag argument. Then it can accept either this

          tar -x -v -f  some_filename.tar

or this, where several flag arguments are specified together

          tar -xvf some_filename.tar

Here is where the distinction between the single-dash sigil and the double-dash sigil becomes important.

  • "-xvf" indicates the concatenation of three single-character flags: “x”, “v”, and “f”.
  • "--xvf" (note the double dash) indicates a single multi-character flag: “xvf”.

Parsing the command line

In many of the examples that we’ve seen, parsing the command line is as simple as splitting it on whitespace. But the situation gets more complicated if values can contain whitespace. If that is true, then we need to support delimiters that can enclose values that contain whitespace.

Suppose we want to invoke a word-processor from the command line. And we want to specify two arguments on the command line: the name of the file, and the name of the author. This obviously will not work.

          superedit A Christmas Story.doc  Clement Moore

What we need is this.

          superedit "A Christmas Story.doc"  "Clement Moore"

Support of quoted values means that command-line parsers must be more sophisticated… just splitting the command line on whitespace won’t do the job. The command-line parser must recognize and correctly handle quote characters… and escaped quote characters inside of quoted strings.

The most common delimiter for argument values is the double-quote symbol. But we might also (or instead) want to support single quotes, back ticks, parentheses, or square/wavy/pointy brackets. We can imagine a case in which a malevolent programmer wrote superedit to expect positional arguments like this.

          superedit (A Christmas Story.doc)  (Clement Moore)

… or named arguments like this.

          superedit filename(A Christmas Story.doc)  author(Clement Moore)

Sigils in positional arguments

Remember our “rename” application? It accepted arguments like this, where the dash is the sigil that introduces the key of a named argument.

          rename  -o file_a.txt  -n file_b.txt

But filenames can begin with dashes. We might need to write a command like this, which would cause problems.

          rename  -o -file_a.txt  -n -file_b.txt

So this is another reason why we might need to be able to quote argument values: to “hide” a sigil character inside a value.

          rename  -o "-file_a.txt"  -n "-file_b.txt"

The order of arguments

In the first version of this post, I wrote that:

It is a universally observed convention that
  • keyword arguments (named arguments and flags) are grouped together
  • positional arguments are grouped together
  • keyword arguments must be specified first, before specifying positional arguments

But that is wrong. It is a widely — but not universally — observed convention. As Eric wrote, in a comment on the first version of this post,

many modern programs allow keyword arguments to be specified after (or even between) positional arguments

And even very old programs do it too. The command-line syntax for Microsoft DOS’s dir command (roughly equivalent to Unix’s ls command) is basically

dir [filename] [switches]

with the filename positional argument appearing before the switches.

A separator between keyword arguments and positional arguments

Suppose we have an application “myprog” that accepts one or more keyword arguments that start with a dash sigil, followed by one or more positional arguments that supply filenames. And suppose that filenames can contain — and begin with — dashes.

We’re going to have a problem if we code this

          myprog -v -r -t -file_a.txt -file_b.txt  -file_c.txt

myprog is going to see “-file_a.txt” and (since it starts with a dash, the sigil) myprog will try to handle it like a keyword argument. Not good.

We could deal with this problem by routinely enclosing all filename positional arguments in quotes, but that would be clumsy and laborious.

          myprog -v -r -t "-file_a.txt" "-file_b.txt"  "-file_c.txt"

An alternative is to use a special string (typically double dashes "--") to indicate the beginning of positional arguments.

          myprog -v -r -t   --  -file_a.txt -file_b.txt  -file_c.txt

So now we have four basic kinds of arguments.

  • positional arguments
  • named arguments (key+value pairs)
  • flags
  • an indicator of the beginning of positional arguments ("--")

Argument semantics

To be expanded…

Optional arguments vs. required argments

Relationships between different arguments

  • Aliases
  • Mutual exclusion
  • Mutual necessity

 

Other variations

In some conventions:

  • Multi-character keys may be abbreviated as long as the abbreviations are unique.
  • The value in a named argument is optional and may be omitted.
  • The value of a named argument may be a list, with items in the list separated by a colon or a comma.
  • A sigil character standing by itself (e.g. a single dash) is treated as a positional argument.

Command-line as a programming language

I think that the best way to think of a command-line, and its arguments, is as a statement in a command-line (CL) programming language, where each application defines its own CL language.

This means that — as far as an application is concerned — the process of using command-line arguments always looks like this:

  1. define (i.e. tell the parsing module about) the syntax rules of the CL language to be used
  2. define (i.e. tell the parsing module about) the semantics of the CL language
  3. call the parser to parse the command line and its arguments
  4. query the parser for information about the “tokens” (the command-line arguments) that it found

Step 2 — specifying the CL semantics — is the step in which the application specifies (for example) what named arguments and flags it accepts, and which are required. This step is necessary for the parser to do certain kinds of semantic checking: (for example) to automatically reject unrecognized keys, or to automatically report required arguments that were not provided.

Step 2 can be omitted, but only if the application itself will do the semantic checking rather than expecting the parsing module to do it.

The upside of doing step 2 is that it enables a smart CL parsing module automatically to generate user documentation for the CL language, and to dump that documentation to the screen when it finds a syntactic or semantic error in the command line, or when the command line is a request (e.g. “/?” or “-h”) for the command-line documentation.

Command-line meta-languages

CL languages are like markup languages. You can invent your own from scratch if you wish, but life is a lot easier if you at least follow some standard conventions when you do.

In the world of markup languages, such standard conventions are called meta-languages. The best-known markup meta-language is XML. XML is not a markup language; it is a markup meta-language … roughly: a style, or set of conventions, or template for creating specific markup languages.

XML is well-defined by the W3C. It would make sense to have similarly well-defined, carefully specified meta-languages for CL languages. Right now, I think we have two loosely-defined CL meta-languages, which I shall refer to as

  • WinCL (for Windows)
  • NixCl (for *nix platforms)

Traditionally (see the Wikipedia article on command line argument)

  • WinCL uses a slash as the sigil; NixCL uses a dash.
  • WinCL uses a colon as a key/value separator; NixCL uses an equal sign.
  • WinCL keywords traditionally consist of a single letter; NixCL is open to multi-character keywords (GNU “long options”).

As of July 25, 2010,:

If it is (or becomes) possible to consider WinCL and NixCL to be well-defined CL meta-languages, then the first step of specifying a CL language for an application (which I gave earlier):

  • define (i.e. tell the parsing module about) the syntax rules of the CL language to be used

could be simply

  • tell the parsing module whether the CL language will be a WinCL or a NixCL language

An alternative is to use a parser utility that is designed to handle specifically WinCL or NixCL. Python’s optparse, for example, “supports only the most common command-line syntax and semantics conventionally used under Unix.” And if you aren’t familiar with those conventions, the documentation summarizes them.

Thinking in Restructured Text

I’ve been trying to learn reST and finding it hard going.  reST just doesn’t seem to work the way I expect it to work.

I don’t know whether the problem lies in reST or in me. It could be me.  I carry a lot of conceptual baggage — it may just be that reST is different from structured-text dialects that I’ve worked with in the past.

Anyway, at this point I am a reST newbie.  As such, I want to find:

  • A few very short, very accessible introductions or tutorials to reST
  • an explanation of reST’s basic “world-view”
  • an online sandbox where I can play with reST, similar to the markdown dingus

1. Introductions

I’ve found these to be pretty useful.

2. Fundamental concepts

I haven’t yet found a good explanation of reST’s world-view.  I suspect it is staring me in the face and I’m just not seeing it.  What I need is for it to be spelled out in big block letters.  And then to be hit over the head with it. Sort of like this:

reST is built on three fundamental concepts: paragraph, indentation, and whitespace.

paragraph

The paragraph is the basic building block of reST. A paragraph is a chunk of text separated from other chunks by one or more blank lines.

reST ignores single newlines, but two or more adjacent newlines (i.e. one or more blank lines) delimit a paragraph.

indentation

Paragraphs must have the same indentation — that is, line up at their left edge. Paragraphs that start indented will result in indented quote paragraphs. For example:

This is a paragraph.  It's quite
short.

   This paragraph will result in an indented block of
   text, typically used for quoting other text.

This is another one.

Results in:

This is a paragraph. It’s quite short.

This paragraph will result in an indented block of text, typically used for quoting other text.

This is another one.

whitespace

The importance of white space is touched on in a tip in the official reST introduction, which talks about inline markup – markup for things like italics, bold, monospaced text, etc.

Think of inline markup as a form of (parentheses) and use it the same way: immediately before and after the text being marked up. Inline markup by itself (surrounded by whitespace) or in the middle of a word won’t be recognized.

reST markup is context-sensitive, or maybe I should say whitespace sensitive. For example, an asterisk in one context creates a bullet for a bullet-list. An asterisk in another context creates inline markup for emphasis (italics). The difference in the context is whether or not the asterisk is or is not preceded or followed by whitespace.

  • An asterisk that is preceded by, but not followed by, whitespace starts italics.
  • An asterisk that is followed by, but not preceded by, whitespace ends italics.
  • Otherwise, an asterisk at the beginning of a line creates a bullet.

This creates emphasis.

some text.
*enclosed text*
some text.

But this creates a bullet item.

some text.
*  enclosed text  *
some text.

3. A reST dingus

I have been able to find an online reST editor.  http://cometdemo.lshift.net:8080/greed/welcome_document/ I’m not quite sure what to call it, so I’ll call it “greed” — that’s a nice memorable name.  In my experience, greed’s page layout doesn’t work very well under Firefox, but works just fine with Internet Explorer.

There is also a pretty nice reST dingus at Siafoo, at www.siafoo.net/tools/reST.

4. Things that I find confusing

I get confused when I read this in the reST documentation:

A paragraph is a chunk of text separated from other chunks by one or more blank lines. … Paragraphs must have the same indentation — that is, line up at their left edge.

Is it saying that the definition of a paragraph is: a chunk of lines that is separated from other chunks of lines by two newlines and contains lines all of which have the same indentation?  What happens if you have a chunk of lines that is delimited by double newlines, but contains lines with different indentation levels?

Let’s see.  Let’s start with these lines.

line A
line B
line C

If we feed these lines to greed, we get:

line A line B line C

No surprises there.

Now let’s add some indentation to line B:

line A
    line B
line C

When we feed this to greed, what we get is roughly (I say “roughly” because in WordPress it is difficult to reproduce the exact HTML that you get from greed) this:

line A
    line B
            System Message: WARNING/2 (<string>, line 3)
            Definition list ends without a  blank line; unexpected unindent.
line C

So reST has rejected a paragraph with irregular indentation.

This is A Good Thing.  reST seems to be acting they way I would expect it to.

Now let’s try putting double newlines after line B, like this:

line A
    line B

line C

When we feed this to greed, it produces roughly this:

line A
    line B

line C

So now I’m confused. In theory, line A and line B form a single, double-newline-delimited paragraph, with irregular indentation.  reST rejected irregular indentation in a paragraph in the previous example, but now reST is accepting irregular indentation and acting as if line B was an indented paragraph. What is going on???!!! (See the answer, below.)

So what happens if we put a double newline after line A?  We get roughly this:

line A

    line B

line C

This is the same result as before, but with more space between line A and line B.  This is what I would have expected.

So what was going on?

My hypothesis is that reST interpreted line A and line B as a definition list — line A being the term, line B being the definition.

The reST docs say that in a definition list, “Blank lines are not allowed between term and definition.”

So (to put it in the most obtuse way possible) a paragraph is a chunk of lines that is separated from other chunks of lines by two newlines. All of the lines in the paragraph must have the same indentation, except when the paragraph is a definition list, in which case the indentation of the definition must be different (greater than) the indentation of the term.

The Bottom Line

I suspect that reST by its very nature has a lot of gotchas.

reST is trying to do so much (e.g. to support advanced markup structures such as definition lists) with so little (simple ASCII text) that it must read a lot into what (in other circumstances) would be meaningless differences.   You might say that reST by its very nature has a very high interpretation-to-signal ratio.

If you are feeling uncharitable, you could say that reST is fragile or flaky; if charitable, you might say that it is very sensitive.   What that adds up to — for at least some newbies — is that it has a lot of gotchas.

So (I’m embarrassed to admit it) I’m still struggling with reST.  Undoubtedly, it is just a matter of time and experience.  I’m pretty sure that if I work with reST long enough — and read all of the documentation — I will eventually grok it.