feeds: Make Feeds.save fully atomic, assuming a working fsync

If the disk is full (or there are other OS-level issues), a file may
not be completely written to the disk.

The write-flush-fsync-rename sequence is much safer.  The fsync
invocation matches the recommendation in the docs [1]:

  If you’re starting with a buffered Python file object f, first do
  f.flush(), and then do os.fsync(f.fileno()), to ensure that all
  internal buffers associated with f are written to disk.

The purpose of each step is:

* write: move the data into a library buffer
* flush: flush the library buffer into a kernel buffer
* fsync: flush the kernel buffer onto the disk at $tempfile
* rename: adjust the metadata so that the $filename points to the
    $tempfile data, release the old data

This means that if the rename works we get the new data, and if the
rename fails we still have the old data.

However, POSIX's fsync is implementation defined unless
_POSIX_SYNCHRONIZED_IO is defined [3,4], and some OS X implementations
go the no-op route, as Stewart Smith points out in his excellent "Eat
My Data: How everybody gets file I/O wrong" [4].  If you want to run
rss2email on such a system, verifying your data integrity is up to you
;).

We used to write-rename the data file (but not the config) on *nix
[2].  Now we do the full write-flush-fsync-rename for both the config
and data files on both *nix and other systems.

[1]: http://docs.python.org/3/library/os.html#os.fsync
[2]: For rss2email, *nix is "has fcntl, but isn't SunOS
[3]: http://pubs.opengroup.org/onlinepubs/009695399/functions/fsync.html
[4]: https://www.flamingspork.com/talks/2007/06/eat_my_data.odp

Reported-by: Etienne Millon <me@emillon.org>
Signed-off-by: W. Trevor King <wking@tremily.us>
feed: Add 'default' argument to Feed._html2text for HTMLParseError

This allows us to easily fall back on an unconverted string in the
event that the input HTML is malformed.  We already caught
HTMLParseError when converting HTML to plain test for non-html mail,
but we didn't catch it in Feed._get_entry_title.  Now we gracefully
handle the situation by treating the malformed HTML as plain text.
CHANGELOG: Document this branch's atomic saves

Signed-off-by: W. Trevor King <wking@tremily.us>
Merge branch 'robust-file-saving'

* robust-file-saving:
  CHANGELOG: Document this branch's atomic saves
  feeds: Make Feeds.save fully atomic, assuming a working fsync

Signed-off-by: W. Trevor King <wking@tremily.us>
CHANGELOG: Document this branch's HTML-title conversion fallback

Signed-off-by: W. Trevor King <wking@tremily.us>
Merge branch 'catch-html-parse-error'

* catch-html-parse-error:
  CHANGELOG: Document this branch's HTML-title conversion fallback
  feed: Add 'default' argument to Feed._html2text for HTMLParseError

Signed-off-by: W. Trevor King <wking@tremily.us>
README: Three-space indents for nested enumerated lists

Apparently two spaces doesn't cut it.  This change fixes:

  $ rst2html.py --strict README
  README:5: (INFO/1) Enumerated list start value not ordinal-1: "3" (ordinal 3)
  Exiting due to level-1 (INFO) system message.

I also use a bullet list for dependencies, because the order in which
you install them doesn't matter to me.

Signed-off-by: W. Trevor King <wking@tremily.us>
setup.py: Claim support for Python 3.3

We've supported 3.3 for the whole rss2email 3.x branch, but I forgot
to mention it in the trove classifiers.

Signed-off-by: W. Trevor King <wking@tremily.us>
Bump to version 3.7

Signed-off-by: W. Trevor King <wking@tremily.us>
MANIFEST.in: Add the AUTHORS file for distribution

Reported-by: Arun Persaud <apersaud@lbl.gov>
Signed-off-by: W. Trevor King <wking@tremily.us>
command: Sluggify feed names on opmlimport

Gaëtan Harter writes [1]:
> Importing the following opml file fails with `invalid feed name
> 'Arch Linux: Recent news updates`
>
>   <?xml version="1.0" encoding="UTF-8"?>
>   <opml version="1.0">
>     <head>
>       <title>Google reader export</title>
>     </head>
>     <body>
>       <outline text="Arch Linux: Recent news updates"
>                title="Arch Linux: Recent news updates" type="rss"
>                xmlUrl="http://www.archlinux.org/feeds/news/"
>                htmlUrl="https://www.archlinux.org/news/" />
>     </body>
>   </opml>
>
> It fails because the `text` field is used directly as `name` for
> creating a Feed object.

ConfigParser can handle colons and accented characters in their
section names [2], but Feed._set_name checks names against
Feed._name_regexp which only allows ASCII letters, digits, periods,
underscores, and the hyphen-minus (U+002D).  Add an inverse
name_slug_regexp to opmlimport that replaces any runs of illegal
characters with a single hyphen-minus, to avoid crashing if the text
attribute contains anything illegal.

[1]: https://github.com/wking/rss2email/issues/24#issuecomment-26224593
[2]: http://docs.python.org/3/library/configparser.html#supported-ini-file-structure

Reported-by: Gaëtan Harter <hartergaetan@gmail.com>
Signed-off-by: W. Trevor King <wking@tremily.us>
feed: Adjust Feed._name_regexp to allow non-ASCII characters

There's no need to restrict folks to the Latin alphabet.

Signed-off-by: W. Trevor King <wking@tremily.us>
CHANGELOG: Document this branch

Signed-off-by: W. Trevor King <wking@tremily.us>
Merge branch 'opmlimport-feed-name-slugging'

* opmlimport-feed-name-slugging:
  CHANGELOG: Document this branch
  feed: Adjust Feed._name_regexp to allow non-ASCII characters
  command: Sluggify feed names on opmlimport

Signed-off-by: W. Trevor King <wking@tremily.us>