aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatěj Cepl <mcepl@redhat.com>2012-02-23 16:44:57 +0100
committerMatěj Cepl <mcepl@redhat.com>2012-02-23 19:54:04 +0100
commit170d827e642de4980049c2ea71ebcf1852e29c9c (patch)
tree0663acce589b5a288cb2ff2ac29e8e23307e2a70
parent91e4adcbc3e7bd459b52cd98a1cdd9239998b09f (diff)
downloadyamlish-170d827e642de4980049c2ea71ebcf1852e29c9c.tar.gz
Input/Read test succeed!
-rw-r--r--failing_test.py49
-rw-r--r--pyyaml/YAMLish.html353
-rw-r--r--pyyaml/YAMLish_files/commonPrint.css290
-rw-r--r--pyyaml/YAMLish_files/gnu-fdl.pngbin0 -> 1748 bytes
-rw-r--r--pyyaml/YAMLish_files/handheld.css1337
-rw-r--r--pyyaml/YAMLish_files/index.js9
-rw-r--r--pyyaml/YAMLish_files/poweredby_mediawiki_88x31.pngbin0 -> 1933 bytes
-rw-r--r--pyyaml/YAMLish_files/wikibits.js1246
-rw-r--r--test-perl.pl67
-rw-r--r--test/__init__.py81
-rw-r--r--test/all_tests.py16
-rw-r--r--test/test_input.py157
-rw-r--r--test/test_load.py8
-rw-r--r--test/test_output.py10
-rw-r--r--test/test_reader.py212
-rw-r--r--test/test_writer.py40
-rw-r--r--yamlish.py262
17 files changed, 3755 insertions, 382 deletions
diff --git a/failing_test.py b/failing_test.py
new file mode 100644
index 0000000..3a4e88c
--- /dev/null
+++ b/failing_test.py
@@ -0,0 +1,49 @@
+#!/usr/bin/python
+import yaml
+
+IN = {
+ "name": 'Hello World 6',
+ "in": [
+ "---",
+ "- \"\\z\\x01\\x02\\x03\\x04\\x05\\x06\\a\\x08\\t\\n\\v\\f\\r\\x0e\\x0f\"",
+ "- \"\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\e\\x1c\\x1d\\x1e\\x1f\"",
+ "- \" !\\\"#\$%&'()*+,-./\"",
+ "- 0123456789:;<=>?",
+ "- '\@ABCDEFGHIJKLMNO'",
+ "- 'PQRSTUVWXYZ[\\]^_'",
+ "- '`abcdefghijklmno'",
+ "- 'pqrstuvwxyz{|}~\177'",
+ "- \200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217",
+ "- \220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237",
+ "- \240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257",
+ "- \260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277",
+ "- \300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317",
+ "- \320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337",
+ "- \340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357",
+ "- \360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377",
+ "..."],
+ "out": [
+ "\0\1\2\3\4\5\6\a\b\t\n\13\f\r\16\17",
+ "\20\21\22\23\24\25\26\27\30\31\32\e\34\35\36\37",
+ " !\"#\$%&'()*+,-./",
+ "0123456789:;<=>?",
+ "\@ABCDEFGHIJKLMNO",
+ "PQRSTUVWXYZ[\\]^_",
+ "`abcdefghijklmno",
+ "pqrstuvwxyz{|}~\177",
+ "\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217",
+ "\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237",
+ "\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257",
+ "\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277",
+ "\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317",
+ "\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337",
+ "\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357",
+ "\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377"
+ ]
+ }
+
+instr = "\n".join(IN['in'])
+print "type instr = %s" % type(instr)
+print instr
+res = yaml.load(instr, Loader=yaml.SafeLoader)
+print "'%s'" % (res == IN['out'])
diff --git a/pyyaml/YAMLish.html b/pyyaml/YAMLish.html
new file mode 100644
index 0000000..bebe084
--- /dev/null
+++ b/pyyaml/YAMLish.html
@@ -0,0 +1,353 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" dir="ltr" lang="en"><head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta name="keywords" content="YAMLish,TAP::Parser,TAP diagnostic syntax">
+ <link rel="shortcut icon" href="http://testanything.org/favicon.ico">
+ <link rel="search" type="application/opensearchdescription+xml" href="http://testanything.org/wiki/opensearch_desc.php" title="Test Anything Protocol (English)">
+ <link title="Creative Commons" type="application/rdf+xml" href="http://testanything.org/wiki/index.php?title=YAMLish&amp;action=creativecommons" rel="meta">
+ <link rel="copyright" href="http://www.gnu.org/copyleft/fdl.html">
+ <title>YAMLish - Test Anything Protocol</title>
+ <style type="text/css" media="screen,projection">/*<![CDATA[*/ @import "/wiki/skins/monobook/main.css?63"; /*]]>*/</style>
+ <link rel="stylesheet" type="text/css" media="print" href="YAMLish_files/commonPrint.css">
+ <link rel="stylesheet" type="text/css" media="handheld" href="YAMLish_files/handheld.css">
+ <!--[if lt IE 5.5000]><style type="text/css">@import "/wiki/skins/monobook/IE50Fixes.css?63";</style><![endif]-->
+ <!--[if IE 5.5000]><style type="text/css">@import "/wiki/skins/monobook/IE55Fixes.css?63";</style><![endif]-->
+ <!--[if IE 6]><style type="text/css">@import "/wiki/skins/monobook/IE60Fixes.css?63";</style><![endif]-->
+ <!--[if IE 7]><style type="text/css">@import "/wiki/skins/monobook/IE70Fixes.css?63";</style><![endif]-->
+ <!--[if lt IE 7]><script type="text/javascript" src="/wiki/skins/common/IEFixes.js?63"></script>
+ <meta http-equiv="imagetoolbar" content="no" /><![endif]-->
+
+ <script type="text/javascript">/*<![CDATA[*/
+var skin = "monobook";
+var stylepath = "/wiki/skins";
+var wgArticlePath = "/wiki/index.php/$1";
+var wgScriptPath = "/wiki";
+var wgServer = "http://testanything.org";
+var wgCanonicalNamespace = "";
+var wgCanonicalSpecialPageName = false;
+var wgNamespaceNumber = 0;
+var wgPageName = "YAMLish";
+var wgTitle = "YAMLish";
+var wgAction = "view";
+var wgArticleId = "1384";
+var wgIsArticle = true;
+var wgUserName = null;
+var wgUserGroups = null;
+var wgUserLanguage = "en";
+var wgContentLanguage = "en";
+var wgBreakFrames = false;
+var wgCurRevisionId = "2084";
+/*]]>*/</script>
+
+ <script type="text/javascript" src="YAMLish_files/wikibits.js"><!-- wikibits js --></script>
+ <script type="text/javascript" src="YAMLish_files/index.js"><!-- site js --></script>
+ <style type="text/css">/*<![CDATA[*/
+@import "/wiki/index.php?title=MediaWiki:Common.css&usemsgcache=yes&action=raw&ctype=text/css&smaxage=18000";
+@import "/wiki/index.php?title=MediaWiki:Monobook.css&usemsgcache=yes&action=raw&ctype=text/css&smaxage=18000";
+@import "/wiki/index.php?title=-&action=raw&gen=css&maxage=18000";
+/*]]>*/</style>
+ <!-- Head Scripts -->
+ </head>
+<body class="mediawiki ns-0 ltr page-YAMLish">
+ <div id="globalWrapper">
+ <div id="column-content">
+ <div id="content">
+ <a name="top" id="top"></a>
+ <h1 class="firstHeading">YAMLish</h1>
+ <div id="bodyContent">
+ <h3 id="siteSub">From Test Anything Protocol</h3>
+ <div id="contentSub"></div>
+ <div id="jump-to-nav">Jump to: <a href="#column-one">navigation</a>, <a href="#searchInput">search</a></div> <!-- start content -->
+ <p>YAMLish is a small subset of YAML that TAP producers may use to embed machine readable information in TAP diagnostics. See <a href="http://testanything.org/wiki/index.php/TAP_diagnostic_syntax" title="TAP diagnostic syntax">TAP diagnostic syntax</a> for information about how YAMLish embeds in TAP.
+</p>
+<table id="toc" class="toc" summary="Contents"><tbody><tr><td><div id="toctitle"><h2>Contents</h2></div>
+<ul>
+<li class="toclevel-1"><a href="#Objectives"><span class="tocnumber">1</span> <span class="toctext">Objectives</span></a></li>
+<li class="toclevel-1"><a href="#Syntax"><span class="tocnumber">2</span> <span class="toctext">Syntax</span></a></li>
+<li class="toclevel-1"><a href="#Root_Namespace"><span class="tocnumber">3</span> <span class="toctext">Root Namespace</span></a></li>
+<li class="toclevel-1"><a href="#Implementations"><span class="tocnumber">4</span> <span class="toctext">Implementations</span></a>
+<ul>
+<li class="toclevel-2"><a href="#Perl"><span class="tocnumber">4.1</span> <span class="toctext">Perl</span></a></li>
+<li class="toclevel-2"><a href="#PHP"><span class="tocnumber">4.2</span> <span class="toctext">PHP</span></a></li>
+</ul>
+</li>
+<li class="toclevel-1"><a href="#Q.26A"><span class="tocnumber">5</span> <span class="toctext">Q&amp;A</span></a>
+<ul>
+<li class="toclevel-2"><a href="#Why_YAML.3F"><span class="tocnumber">5.1</span> <span class="toctext">Why YAML?</span></a></li>
+<li class="toclevel-2"><a href="#Why_not_JSON.3F"><span class="tocnumber">5.2</span> <span class="toctext">Why not JSON?</span></a></li>
+<li class="toclevel-2"><a href="#Why_the_---_and_..._markers.3F"><span class="tocnumber">5.3</span> <span class="toctext">Why the --- and ... markers?</span></a></li>
+</ul>
+</li>
+</ul>
+</td></tr></tbody></table><script type="text/javascript"> if (window.showTocToggle) { var tocShowText = "show"; var tocHideText = "hide"; showTocToggle(); } </script>
+<a name="Objectives"></a><h2><span class="editsection">[<a href="http://testanything.org/wiki/index.php?title=YAMLish&amp;action=edit&amp;section=1" title="Edit section: Objectives">edit</a>]</span> <span class="mw-headline"> Objectives </span></h2>
+<p>The main objectives for YAMLish are
+</p>
+<ul><li> small - the Perl reader is around 124 lines, 258 lines for the parser
+</li><li> portable - it should be reasonably easy to implement YAMLish in any language
+</li><li> able to encode arbitrary data structures
+</li><li> verifiable - it should be relatively to easy to test that a YAMLish implementation conforms
+</li><li> JSON compatible - YAMLish should be a super-set of JSON to
+allow TAP producers to make use of JSON libraries (objective not met)
+</li></ul>
+<a name="Syntax"></a><h2><span class="editsection">[<a href="http://testanything.org/wiki/index.php?title=YAMLish&amp;action=edit&amp;section=2" title="Edit section: Syntax">edit</a>]</span> <span class="mw-headline"> Syntax </span></h2>
+<p>To avoid the burden of distributing a complete YAML parser with a TAP
+ producer or consumer YAMLish confines itself to a subset of YAML
+syntax.
+</p><p>These examples demonstrates the supported syntax.
+</p><p>All YAMLish documents must begin with '---' and end with a line containing '...'.
+</p>
+<pre> --- Simple scalar
+ ...
+</pre>
+<p>Unprintable characters are represented using standard escapes in double quoted strings.
+</p>
+<pre> --- "\t\x01\x02\n"
+ ...
+</pre>
+<p>Array and hashes are represented thusly
+</p>
+<pre> ---
+ - "This"
+ - "is"
+ - "an"
+ - "array"
+ ...
+</pre>
+<pre> ---
+ This: is
+ a: hash
+ ...
+</pre>
+<p>Hash keys may be double quoted strings and may contain unprintable characters
+</p>
+<pre> ---
+ "\t\x00": "My key is &lt;tab&gt;&lt;nul&gt;"
+ "Now is the time": "t'was ever thus"
+ ...
+
+</pre>
+<p>Structures may nest arbitrarily
+</p>
+<pre> ---
+ -
+ name: 'Hash one'
+ value: 1
+ -
+ name: 'Hash two'
+ value: 2
+ ...
+</pre>
+<p>Undef is a tilde
+</p>
+<pre> --- ~
+ ...
+</pre>
+<a name="Root_Namespace"></a><h2><span class="editsection">[<a href="http://testanything.org/wiki/index.php?title=YAMLish&amp;action=edit&amp;section=3" title="Edit section: Root Namespace">edit</a>]</span> <span class="mw-headline"> Root Namespace </span></h2>
+<p>When used with TAP the root element of an embedded YAMLish diagnostic is a hash containing keys from this set:
+</p>
+<dl><dt> message
+</dt><dd> A textual message giving more detail about the failure (or success)
+</dd><dt> severity
+</dt><dd> The severity of the problem.
+</dd><dt> source
+</dt><dd> A uri describing the source of the TAP. This can be a file URL. See "file" for a special case.
+</dd><dt> datetime
+</dt><dd> the time the test was executed, helping test runners do
+interesting things like run tests in order of most-recently-failed.
+ISO8601 or HTTP date format.
+</dd><dt> file
+</dt><dd> A filename representing the TAP source, really a special case
+of "source". Not possible for all TAP sources, but I really don't want
+everyone to have to use file URIs.
+</dd><dt> line
+</dt><dd> The line number of the TAP source from which this test was produced. Not possible for all TAP sources.
+</dd><dt> name
+</dt><dd> Name of this test, if any.
+</dd><dt> extensions
+</dt><dd> A place to put any non-standard keys without worrying out conflicting with future ones
+</dd><dt> actual
+</dt><dd> For comparison tests, what you got.
+</dd><dt> expected
+</dt><dd> For comparison tests, what you expected.
+</dd><dt> display
+</dt><dd> Suggested text to display representing this failure
+</dd><dt> dump
+</dt><dd> A hash of variables to be pretty-printed by the harness
+</dd><dt> error
+</dt><dd> An error or exception object
+</dd><dt> backtrace
+</dt><dd> A stack backtrace in the case of an error or exception
+</dd></dl>
+<p>(please feel free to add to this list - it's provisional at the moment)
+</p>
+<a name="Implementations"></a><h2><span class="editsection">[<a href="http://testanything.org/wiki/index.php?title=YAMLish&amp;action=edit&amp;section=4" title="Edit section: Implementations">edit</a>]</span> <span class="mw-headline"> Implementations </span></h2>
+<p>Because YAMLish is a subset of YAML there are already a number of
+parsers in a number of languages that accept it. It's also quite likely
+that existing YAML producers can be coerced into producing YAMLish
+compliant YAML. Please be careful though to ensure that your YAMLish
+producer does in fact conform to the subset defined here. Just because
+your YAML happens to work with a particular test harness doesn't mean
+that it's valid YAMLish.
+</p><p>YAMLish is based on the subset of YAML supported by Adam Kennedy's <a href="http://search.cpan.org/dist/YAML-Tiny" class="external text" title="http://search.cpan.org/dist/YAML-Tiny" rel="nofollow">YAML::Tiny</a>
+ Perl module. YAML::Tiny doesn't support quoted hash keys - which we
+need so that we can safely round-trip arbitrary data structures - so
+YAMLish extends Adam's de-facto subset to include these.
+</p><p>If your concern is only to produce well formed TAP (rather than
+parsing it) then you should find that it's possible to implement a
+YAMLish writer in a couple of hundred lines of code.
+</p>
+<a name="Perl"></a><h3><span class="editsection">[<a href="http://testanything.org/wiki/index.php?title=YAMLish&amp;action=edit&amp;section=5" title="Edit section: Perl">edit</a>]</span> <span class="mw-headline"> Perl </span></h3>
+<ul><li> <a href="http://testanything.org/wiki/index.php/TAP::Parser" title="TAP::Parser">TAP::Parser</a>
+ implements YAMLish support. You'll need the version from the subversion
+ repository though; YAMLish support hasn't yet made it to CPAN.
+</li><li> <a href="http://search.cpan.org/dist/Data-YAML" class="external text" title="http://search.cpan.org/dist/Data-YAML" rel="nofollow">Data::YAML</a> is essentially the YAMLish engine from TAP::Parser packaged as a standalone module
+</li></ul>
+<a name="PHP"></a><h3><span class="editsection">[<a href="http://testanything.org/wiki/index.php?title=YAMLish&amp;action=edit&amp;section=6" title="Edit section: PHP">edit</a>]</span> <span class="mw-headline"> PHP </span></h3>
+<ul><li> <a href="http://testanything.org/ftp/yamlishwriter-php-v0.0.1.tar.gz" class="external text" title="http://testanything.org/ftp/yamlishwriter-php-v0.0.1.tar.gz" rel="nofollow">YAMLishWriter</a> is a simple PHP implementation of a YAMLish encoder
+</li></ul>
+<p>If you have a YAMLish implementation please list it here.
+</p>
+<a name="Q.26A"></a><h2><span class="editsection">[<a href="http://testanything.org/wiki/index.php?title=YAMLish&amp;action=edit&amp;section=7" title="Edit section: Q&amp;A">edit</a>]</span> <span class="mw-headline"> Q&amp;A </span></h2>
+<a name="Why_YAML.3F"></a><h3><span class="editsection">[<a href="http://testanything.org/wiki/index.php?title=YAMLish&amp;action=edit&amp;section=8" title="Edit section: Why YAML?">edit</a>]</span> <span class="mw-headline"> Why YAML? </span></h3>
+<p>TAP diagnostics require a way to represent data structions in any
+language in a human and machine readable form. It would be nice if we
+didn't have to write our own format. YAML, like TAP, is designed to be
+both human and machine readable as well as language independent. YAML <a href="http://portablegeneratorsforsale.net/" class="external text" title="http://portablegeneratorsforsale.net/" rel="nofollow">portable generators</a> and parsers already exist in many languages. <a href="http://portablesgenerators.com/" class="external text" title="http://portablesgenerators.com/" rel="nofollow">portable generators</a> YAML has already solved the hard problems facing a data serialization format (like character sets).
+</p>
+<a name="Why_not_JSON.3F"></a><h3><span class="editsection">[<a href="http://testanything.org/wiki/index.php?title=YAMLish&amp;action=edit&amp;section=9" title="Edit section: Why not JSON?">edit</a>]</span> <span class="mw-headline"> Why not JSON? </span></h3>
+<p>JSON was considered, and it has some of the characteristics of YAML, but it was ultimately rejected for several reasons.
+</p><p>JSON is, effectively, a subset of YAML. If your producer emits JSON then a YAML parser will read it. The inverse is not true.
+</p><p>JSON is more verbose, less human readable, requiring more quoting. For example:
+</p>
+<pre> # YAML
+ ---
+ got: this
+ expected: that
+ ...
+
+ # JSON
+ {
+ "got": "this"
+ "expected": "that"
+ }
+</pre>
+<p>JSON lacks a WYSIWYG multi-line scalar value format. YAML has
+several. | allows the exact text to be presented, newlines and all.
+&gt; "soft wraps" text to prevent long lines from spilling across the
+screen.
+</p>
+<pre> # YAML
+ ---
+ got: &gt;
+ When in the course of human events,
+ blah blah blah
+ expected: &gt;
+ When, in the course of human events,
+ it becomes necessary for one people to
+ dissolve the political bonds which have
+ connected them with another...
+ ...
+</pre>
+<pre> # JSON
+ {
+ "got": "When in the course of human events, blah blah blah"
+ "expected": "When, in the course of human events, it becomes necessary for one people to dissolve the political bonds which have connected them with another..."
+ }
+</pre>
+<a name="Why_the_---_and_..._markers.3F"></a><h3><span class="editsection">[<a href="http://testanything.org/wiki/index.php?title=YAMLish&amp;action=edit&amp;section=10" title="Edit section: Why the --- and ... markers?">edit</a>]</span> <span class="mw-headline"> Why the --- and ... markers? </span></h3>
+<p>With the diagnostics indented to indicate they're diagnostics, why
+the --- and ... markers? TAP producers tend to spit a lot of junk to
+STDOUT, either explicitly as poorly written comments or accidentally
+because the thing they're testing prints to STDOUT. We don't want just
+any old indented text to be parsed, so we put the --- and ... markers
+around it. The --- is there to indicate the start of a block. The ...
+is there to indicate it has ended so the parser does not have to wait
+for the next test line (which could take a while) to know there's no
+more diagnostics for the previous test forthcoming.
+</p>
+<!-- Saved in parser cache with key testanything:pcache:idhash:1384-0!1!0!!en!2 and timestamp 20120215030008 -->
+<div class="printfooter">
+Retrieved from "<a href="http://testanything.org/wiki/index.php/YAMLish">http://testanything.org/wiki/index.php/YAMLish</a>"</div>
+ <div id="catlinks"><p class="catlinks"><a href="http://testanything.org/wiki/index.php/Special:Categories" title="Special:Categories">Categories</a>: <span dir="ltr"><a href="http://testanything.org/wiki/index.php?title=Category:Proposals&amp;action=edit" class="new" title="Category:Proposals">Proposals</a></span> | <span dir="ltr"><a href="http://testanything.org/wiki/index.php?title=Category:YAMLish&amp;action=edit" class="new" title="Category:YAMLish">YAMLish</a></span></p></div> <!-- end content -->
+ <div class="visualClear"></div>
+ </div>
+ </div>
+ </div>
+ <div id="column-one">
+ <div id="p-cactions" class="portlet">
+ <h5>Views</h5>
+ <div class="pBody">
+ <ul>
+ <li id="ca-nstab-main" class="selected"><a href="http://testanything.org/wiki/index.php/YAMLish" title="View the content page [c]" accesskey="c">Article</a></li>
+ <li id="ca-talk"><a href="http://testanything.org/wiki/index.php/Talk:YAMLish" title="Discussion about the content page [t]" accesskey="t">Discussion</a></li>
+ <li id="ca-edit"><a href="http://testanything.org/wiki/index.php?title=YAMLish&amp;action=edit" title="You can edit this page. Please use the preview button before saving. [e]" accesskey="e">Edit</a></li>
+ <li id="ca-history"><a href="http://testanything.org/wiki/index.php?title=YAMLish&amp;action=history" title="Past versions of this page. [h]" accesskey="h">History</a></li>
+ </ul>
+ </div>
+ </div>
+ <div class="portlet" id="p-personal">
+ <h5>Personal tools</h5>
+ <div class="pBody">
+ <ul>
+ <li id="pt-login"><a href="http://testanything.org/wiki/index.php?title=Special:Userlogin&amp;returnto=YAMLish" title="You are encouraged to log in, it is not mandatory however. [o]" accesskey="o">Log in / create account</a></li>
+ </ul>
+ </div>
+ </div>
+ <div class="portlet" id="p-logo">
+ <a style="background-image: url(&quot;/i/tap.png&quot;);" href="http://testanything.org/wiki/index.php/Main_Page" title="Visit the Main Page [z]" accesskey="z"></a>
+ </div>
+ <script type="text/javascript"> if (window.isMSIE55) fixalpha(); </script>
+ <div class="portlet" id="p-navigation">
+ <h5>Navigation</h5>
+ <div class="pBody">
+ <ul>
+ <li id="n-mainpage"><a href="http://testanything.org/wiki/index.php/Main_Page" title="Visit the Main Page [z]" accesskey="z">Main Page</a></li>
+ <li id="n-portal"><a href="http://testanything.org/wiki/index.php/Test_Anything_Protocol:Community_Portal" title="About the project, what you can do, where to find things">Community portal</a></li>
+ <li id="n-currentevents"><a href="http://testanything.org/wiki/index.php/Current_events" title="Find background information on current events">Current events</a></li>
+ <li id="n-recentchanges"><a href="http://testanything.org/wiki/index.php/Special:Recentchanges" title="The list of recent changes in the wiki. [r]" accesskey="r">Recent changes</a></li>
+ <li id="n-randompage"><a href="http://testanything.org/wiki/index.php/Special:Random" title="Load a random page [x]" accesskey="x">Random page</a></li>
+ <li id="n-help"><a href="http://testanything.org/wiki/index.php/Help:Contents" title="The place to find out.">Help</a></li>
+ </ul>
+ </div>
+ </div>
+ <div id="p-search" class="portlet">
+ <h5><label for="searchInput">Search</label></h5>
+ <div id="searchBody" class="pBody">
+ <form action="/wiki/index.php/Special:Search" id="searchform"><div>
+ <input id="searchInput" name="search" title="Search Test Anything Protocol [f]" accesskey="f" type="text">
+ <input name="go" class="searchButton" id="searchGoButton" value="Go" type="submit">&nbsp;
+ <input name="fulltext" class="searchButton" id="mw-searchButton" value="Search" type="submit">
+ </div></form>
+ </div>
+ </div>
+ <div class="portlet" id="p-tb">
+ <h5>Toolbox</h5>
+ <div class="pBody">
+ <ul>
+ <li id="t-whatlinkshere"><a href="http://testanything.org/wiki/index.php/Special:Whatlinkshere/YAMLish" title="List of all wiki pages that link here [j]" accesskey="j">What links here</a></li>
+ <li id="t-recentchangeslinked"><a href="http://testanything.org/wiki/index.php/Special:Recentchangeslinked/YAMLish" title="Recent changes in pages linked from this page [k]" accesskey="k">Related changes</a></li>
+<li id="t-specialpages"><a href="http://testanything.org/wiki/index.php/Special:Specialpages" title="List of all special pages [q]" accesskey="q">Special pages</a></li>
+ <li id="t-print"><a href="http://testanything.org/wiki/index.php?title=YAMLish&amp;printable=yes">Printable version</a></li> <li id="t-permalink"><a href="http://testanything.org/wiki/index.php?title=YAMLish&amp;oldid=2084">Permanent link</a></li> </ul>
+ </div>
+ </div>
+ </div><!-- end of the left (by default at least) column -->
+ <div class="visualClear"></div>
+ <div id="footer">
+ <div id="f-poweredbyico"><a href="http://www.mediawiki.org/"><img src="YAMLish_files/poweredby_mediawiki_88x31.png" alt="Powered by MediaWiki"></a></div>
+ <div id="f-copyrightico"><a href="http://www.gnu.org/copyleft/fdl.html"><img src="YAMLish_files/gnu-fdl.png" alt="GNU Free Documentation License 1.2"></a></div>
+ <ul id="f-list">
+ <li id="lastmod"> This page was last modified 19:32, 8 December 2010.</li>
+ <li id="viewcount">This page has been accessed 16,053 times.</li>
+ <li id="copyright">Content is available under <a href="http://www.gnu.org/copyleft/fdl.html" class="external " title="http://www.gnu.org/copyleft/fdl.html" rel="nofollow">GNU Free Documentation License 1.2</a>.</li>
+ <li id="privacy"><a href="http://testanything.org/wiki/index.php/Test_Anything_Protocol:Privacy_policy" title="Test Anything Protocol:Privacy policy">Privacy policy</a></li>
+ <li id="about"><a href="http://testanything.org/wiki/index.php/Test_Anything_Protocol:About" title="Test Anything Protocol:About">About Test Anything Protocol</a></li>
+ <li id="disclaimer"><a href="http://testanything.org/wiki/index.php/Test_Anything_Protocol:General_disclaimer" title="Test Anything Protocol:General disclaimer">Disclaimers</a></li>
+ </ul>
+ </div>
+
+
+ <script type="text/javascript">if (window.runOnloadHook) runOnloadHook();</script>
+</div>
+<!-- Served by eric.hexten.net in 0.184 secs. -->
+</body></html> \ No newline at end of file
diff --git a/pyyaml/YAMLish_files/commonPrint.css b/pyyaml/YAMLish_files/commonPrint.css
new file mode 100644
index 0000000..4fddafa
--- /dev/null
+++ b/pyyaml/YAMLish_files/commonPrint.css
@@ -0,0 +1,290 @@
+/*
+** MediaWiki Print style sheet for CSS2-capable browsers.
+** Copyright Gabriel Wicke, http://www.aulinx.de/
+**
+** Derived from the plone (http://plone.org/) styles
+** Copyright Alexander Limi
+*/
+
+/* Thanks to A List Apart (http://alistapart.com/) for useful extras */
+a.stub,
+a.new{ color:#ba0000; text-decoration:none; }
+
+#toc {
+ /*border:1px solid #2f6fab;*/
+ border:1px solid #aaaaaa;
+ background-color:#f9f9f9;
+ padding:5px;
+}
+.tocindent {
+ margin-left: 2em;
+}
+.tocline {
+ margin-bottom: 0px;
+}
+
+/* images */
+div.floatright {
+ float: right;
+ clear: right;
+ margin: 0;
+ position:relative;
+ border: 0.5em solid White;
+ border-width: 0.5em 0 0.8em 1.4em;
+}
+div.floatright p { font-style: italic;}
+div.floatleft {
+ float: left;
+ margin: 0.3em 0.5em 0.5em 0;
+ position:relative;
+ border: 0.5em solid White;
+ border-width: 0.5em 1.4em 0.8em 0;
+}
+div.floatleft p { font-style: italic; }
+/* thumbnails */
+div.thumb {
+ margin-bottom: 0.5em;
+ border-style: solid; border-color: White;
+ width: auto;
+ overflow: hidden;
+}
+div.thumb div {
+ border:1px solid #cccccc;
+ padding: 3px !important;
+ background-color:#f9f9f9;
+ font-size: 94%;
+ text-align: center;
+}
+div.thumb div a img {
+ border:1px solid #cccccc;
+}
+div.thumb div div.thumbcaption {
+ border: none;
+ padding: 0.3em 0 0.1em 0;
+}
+div.magnify { display: none; }
+div.tright {
+ float: right;
+ clear: right;
+ border-width: 0.5em 0 0.8em 1.4em;
+}
+div.tleft {
+ float: left;
+ margin-right:0.5em;
+ border-width: 0.5em 1.4em 0.8em 0;
+}
+
+/* table standards */
+table.rimage {
+ float:right;
+ width:1pt;
+ position:relative;
+ margin-left:1em;
+ margin-bottom:1em;
+ text-align:center;
+}
+
+body {
+ background: White;
+ /*font-size: 11pt !important;*/
+ color: Black;
+ margin: 0;
+ padding: 0;
+}
+
+.noprint,
+div#jump-to-nav,
+div.top,
+div#column-one,
+#colophon,
+.editsection,
+.toctoggle,
+.tochidden,
+div#f-poweredbyico,
+div#f-copyrightico,
+li#viewcount,
+li#about,
+li#disclaimer,
+li#privacy {
+ /* Hides all the elements irrelevant for printing */
+ display: none;
+}
+
+ul {
+ list-style-type: square;
+}
+
+#content {
+ background: none;
+ border: none ! important;
+ padding: 0 ! important;
+ margin: 0 ! important;
+}
+#footer {
+ background : white;
+ color : black;
+ border-top: 1px solid black;
+}
+
+h1, h2, h3, h4, h5, h6
+{
+ font-weight: bold;
+}
+
+p, .documentDescription {
+ margin: 1em 0 ! important;
+ line-height: 1.2em;
+}
+
+.tocindent p {
+ margin: 0 0 0 0 ! important;
+}
+
+pre {
+ border: 1pt dashed black;
+ white-space: pre;
+ font-size: 8pt;
+ overflow: auto;
+ padding: 1em 0;
+ background : white;
+ color : black;
+}
+
+table.listing,
+table.listing td {
+ border: 1pt solid black;
+ border-collapse: collapse;
+}
+
+a {
+ color: Black !important;
+ background: none !important;
+ padding: 0 !important;
+}
+
+a:link, a:visited {
+ color: #520;
+ background: transparent;
+ text-decoration: underline;
+}
+
+#content a.external.text:after, #content a.external.autonumber:after {
+ /* Expand URLs for printing */
+ content: " (" attr(href) ") ";
+}
+
+#globalWrapper {
+ width: 100% !important;
+ min-width: 0 !important;
+}
+
+#content {
+ background : white;
+ color : black;
+}
+
+#column-content {
+ margin: 0 !important;
+}
+
+#column-content #content {
+ padding: 1em;
+ margin: 0 !important;
+}
+/* MSIE/Win doesn't understand 'inherit' */
+a, a.external, a.new, a.stub {
+ color: black ! important;
+ text-decoration: none ! important;
+}
+
+/* Continue ... */
+a, a.external, a.new, a.stub {
+ color: inherit ! important;
+ text-decoration: inherit ! important;
+}
+
+img { border: none; }
+img.tex { vertical-align: middle; }
+span.texhtml { font-family: serif; }
+
+div.townBox {
+ position:relative;
+ float:right;
+ background:White;
+ margin-left:1em;
+ border: 1px solid gray;
+ padding:0.3em;
+ width: 200px;
+ overflow: hidden;
+ clear: right;
+}
+div.townBox dl {
+ padding: 0;
+ margin: 0 0 0.3em 0;
+ font-size: 96%;
+}
+div.townBox dl dt {
+ background: none;
+ margin: 0.4em 0 0 0;
+}
+div.townBox dl dd {
+ margin: 0.1em 0 0 1.1em;
+ background-color: #f3f3f3;
+}
+
+#siteNotice { display: none; }
+
+table.gallery {
+ border: 1px solid #cccccc;
+ margin: 2px;
+ padding: 2px;
+ background-color:#ffffff;
+}
+
+table.gallery tr {
+ vertical-align:top;
+}
+
+div.gallerybox {
+ border: 1px solid #cccccc;
+ margin: 2px;
+ background-color:#f9f9f9;
+ width: 150px;
+}
+
+div.gallerybox div.thumb {
+ text-align: center;
+ border: 1px solid #cccccc;
+ margin: 2px;
+}
+
+div.gallerytext {
+ font-size: 94%;
+ padding: 2px 4px;
+}
+
+/*
+** Diff rendering
+*/
+table.diff { background:white; }
+td.diff-otitle { background:#ffffff; }
+td.diff-ntitle { background:#ffffff; }
+td.diff-addedline {
+ background:#ccffcc;
+ font-size: smaller;
+ border: solid 2px black;
+}
+td.diff-deletedline {
+ background:#ffffaa;
+ font-size: smaller;
+ border: dotted 2px black;
+}
+td.diff-context {
+ background:#eeeeee;
+ font-size: smaller;
+}
+.diffchange {
+ color: silver;
+ font-weight: bold;
+ text-decoration: underline;
+}
diff --git a/pyyaml/YAMLish_files/gnu-fdl.png b/pyyaml/YAMLish_files/gnu-fdl.png
new file mode 100644
index 0000000..1371aba
--- /dev/null
+++ b/pyyaml/YAMLish_files/gnu-fdl.png
Binary files differ
diff --git a/pyyaml/YAMLish_files/handheld.css b/pyyaml/YAMLish_files/handheld.css
new file mode 100644
index 0000000..754aba9
--- /dev/null
+++ b/pyyaml/YAMLish_files/handheld.css
@@ -0,0 +1,1337 @@
+/*
+** MediaWiki 'monobook' style sheet for CSS2-capable browsers.
+** Copyright Gabriel Wicke - http://wikidev.net/
+** License: GPL (http://www.gnu.org/copyleft/gpl.html)
+**
+** Loosely based on http://www.positioniseverything.net/ordered-floats.html by Big John
+** and the Plone 2.0 styles, see http://plone.org/ (Alexander Limi,Joe Geldart & Tom Croucher,
+** Michael Zeltner and Geir Bækholt)
+** All you guys rock :)
+*/
+
+/**
+ * Stylesheet for handhelds. All rules not marked media-specific are shared
+ * with main.css and should be updated in tandem. The rules can't be in the
+ * same file because old browsers like IE5 won't obey @media rules.
+ *
+ * Rules that are handheld-specific are given @media rules in case old browsers
+ * don't recognize the media attribute and load this file anyway.
+ */
+
+#content {
+ background: white;
+ color: black;
+ border: 1px solid #aaa;
+ border-right: none;
+ line-height: 1.5em;
+}
+/* the left column width is specified in class .portlet */
+
+/* Font size:
+** We take advantage of keyword scaling- browsers won't go below 9px
+** More at http://www.w3.org/2003/07/30-font-size
+** http://style.cleverchimp.com/font_size_intervals/altintervals.html
+*/
+
+body {
+ font: x-small sans-serif;
+ background: #f9f9f9 url(headbg.jpg) 0 0 no-repeat;
+ color: black;
+ margin: 0;
+ padding: 0;
+}
+
+/* scale back up to a sane default */
+#globalWrapper {
+ font-size: 127%;
+ width: 100%;
+ margin: 0;
+ padding: 0;
+}
+.visualClear {
+ clear: both;
+}
+
+/* general styles */
+
+table {
+ font-size: 100%;
+ color: black;
+ /* we don't want the bottom borders of <h2>s to be visible through
+ floated tables */
+ background-color: white;
+}
+a {
+ text-decoration: none;
+ color: #002bb8;
+ background: none;
+}
+a:visited {
+ color: #5a3696;
+}
+a:active {
+ color: #faa700;
+}
+a:hover {
+ text-decoration: underline;
+}
+a.stub {
+ color: #772233;
+}
+a.new, #p-personal a.new {
+ color: #ba0000;
+}
+a.new:visited, #p-personal a.new:visited {
+ color: #a55858;
+}
+
+img {
+ border: none;
+ vertical-align: middle;
+}
+p img {
+ margin: 0;
+}
+
+hr {
+ height: 1px;
+ color: #aaa;
+ background-color: #aaa;
+ border: 0;
+ margin: .2em 0 .2em 0;
+}
+
+h1, h2, h3, h4, h5, h6 {
+ color: black;
+ background: none;
+ font-weight: normal;
+ margin: 0;
+ padding-top: .5em;
+ padding-bottom: .17em;
+ border-bottom: 1px solid #aaa;
+}
+h1 { font-size: 188%; }
+h1 .editsection { font-size: 53%; }
+h2 { font-size: 150%; }
+h2 .editsection { font-size: 67%; }
+h3, h4, h5, h6 {
+ border-bottom: none;
+ font-weight: bold;
+}
+h3 { font-size: 132%; }
+h3 .editsection { font-size: 76%; font-weight: normal; }
+h4 { font-size: 116%; }
+h4 .editsection { font-size: 86%; font-weight: normal; }
+h5 { font-size: 100%; }
+h5 .editsection { font-weight: normal; }
+h6 { font-size: 80%; }
+h6 .editsection { font-size: 125%; font-weight: normal; }
+
+.editsection {
+ float: right;
+ margin-left: 5px;
+}
+
+ul {
+ line-height: 1.5em;
+ list-style-type: square;
+ margin: .3em 0 0 1.5em;
+ padding: 0;
+ list-style-image: url(bullet.gif);
+}
+ol {
+ line-height: 1.5em;
+ margin: .3em 0 0 3.2em;
+ padding: 0;
+ list-style-image: none;
+}
+li {
+ margin-bottom: .1em;
+}
+dt {
+ font-weight: bold;
+ margin-bottom: .1em;
+}
+dl {
+ margin-top: .2em;
+ margin-bottom: .5em;
+}
+dd {
+ line-height: 1.5em;
+ margin-left: 2em;
+ margin-bottom: .1em;
+}
+
+fieldset {
+ border: 1px solid #2f6fab;
+ margin: 1em 0 1em 0;
+ padding: 0 1em 1em;
+ line-height: 1.5em;
+}
+legend {
+ padding: .5em;
+ font-size: 95%;
+}
+form {
+ border: none;
+ margin: 0;
+}
+
+textarea {
+ width: 100%;
+ padding: .1em;
+}
+
+input.historysubmit {
+ padding: 0 .3em .3em .3em !important;
+ font-size: 94%;
+ cursor: pointer;
+ height: 1.7em !important;
+ margin-left: 1.6em;
+}
+select {
+ vertical-align: top;
+}
+abbr, acronym, .explain {
+ border-bottom: 1px dotted black;
+ color: black;
+ background: none;
+ cursor: help;
+}
+q {
+ font-family: Times, "Times New Roman", serif;
+ font-style: italic;
+}
+/* disabled for now
+blockquote {
+ font-family: Times, "Times New Roman", serif;
+ font-style: italic;
+}*/
+code {
+ background-color: #f9f9f9;
+}
+pre {
+ padding: 1em;
+ border: 1px dashed #2f6fab;
+ color: black;
+ background-color: #f9f9f9;
+ line-height: 1.1em;
+}
+
+/*
+** the main content area
+*/
+
+#contentSub, #contentSub2 {
+ font-size: 84%;
+ line-height: 1.2em;
+ margin: 0 0 1.4em 1em;
+ color: #7d7d7d;
+ width: auto;
+}
+span.subpages {
+ display: block;
+}
+
+/* Some space under the headers in the content area */
+#bodyContent h1, #bodyContent h2 {
+ margin-bottom: .6em;
+}
+#bodyContent h3, #bodyContent h4, #bodyContent h5 {
+ margin-bottom: .3em;
+}
+.firstHeading {
+ margin-bottom: .1em;
+}
+
+/* user notification thing */
+.usermessage {
+ background-color: #ffce7b;
+ border: 1px solid #ffa500;
+ color: black;
+ font-weight: bold;
+ margin: 2em 0 1em;
+ padding: .5em 1em;
+ vertical-align: middle;
+}
+#siteNotice {
+ text-align: center;
+ font-size: 95%;
+ padding: 0 .9em;
+}
+#siteNotice p {
+ margin: 0;
+ padding: 0;
+}
+.error {
+ color: red;
+ font-size: larger;
+}
+.errorbox, .successbox {
+ font-size: larger;
+ border: 2px solid;
+ padding: .5em 1em;
+ float: left;
+ margin-bottom: 2em;
+ color: #000;
+}
+.errorbox {
+ border-color: red;
+ background-color: #fff2f2;
+}
+.successbox {
+ border-color: green;
+ background-color: #dfd;
+}
+.errorbox h2, .successbox h2 {
+ font-size: 1em;
+ font-weight: bold;
+ display: inline;
+ margin: 0 .5em 0 0;
+ border: none;
+}
+
+#catlinks {
+ border: 1px solid #aaa;
+ background-color: #f9f9f9;
+ padding: 5px;
+ margin-top: 1em;
+ clear: both;
+}
+/* currently unused, intended to be used by a metadata box
+in the bottom-right corner of the content area */
+.documentDescription {
+ /* The summary text describing the document */
+ font-weight: bold;
+ display: block;
+ margin: 1em 0;
+ line-height: 1.5em;
+}
+.documentByLine {
+ text-align: right;
+ font-size: 90%;
+ clear: both;
+ font-weight: normal;
+ color: #76797c;
+}
+
+/* emulate center */
+.center {
+ width: 100%;
+ text-align: center;
+}
+*.center * {
+ margin-left: auto;
+ margin-right: auto;
+}
+/* small for tables and similar */
+.small, .small * {
+ font-size: 94%;
+}
+table.small {
+ font-size: 100%;
+}
+
+/*
+** content styles
+*/
+
+#toc,
+.toc,
+.mw-warning {
+ border: 1px solid #aaa;
+ background-color: #f9f9f9;
+ padding: 5px;
+ font-size: 95%;
+}
+#toc h2,
+.toc h2 {
+ display: inline;
+ border: none;
+ padding: 0;
+ font-size: 100%;
+ font-weight: bold;
+}
+#toc #toctitle,
+.toc #toctitle,
+#toc .toctitle,
+.toc .toctitle {
+ text-align: center;
+}
+#toc ul,
+.toc ul {
+ list-style-type: none;
+ list-style-image: none;
+ margin-left: 0;
+ padding-left: 0;
+ text-align: left;
+}
+#toc ul ul,
+.toc ul ul {
+ margin: 0 0 0 2em;
+}
+#toc .toctoggle,
+.toc .toctoggle {
+ font-size: 94%;
+}
+
+.mw-warning {
+ margin-left: 50px;
+ margin-right: 50px;
+ text-align: center;
+}
+
+/* images */
+div.floatright, table.floatright {
+ clear: right;
+ float: right;
+ position: relative;
+ margin: 0 0 .5em .5em;
+ border: 0;
+/*
+ border: .5em solid white;
+ border-width: .5em 0 .8em 1.4em;
+*/
+}
+div.floatright p { font-style: italic; }
+div.floatleft, table.floatleft {
+ float: left;
+ clear: left;
+ position: relative;
+ margin: 0 .5em .5em 0;
+ border: 0;
+/*
+ margin: .3em .5em .5em 0;
+ border: .5em solid white;
+ border-width: .5em 1.4em .8em 0;
+*/
+}
+div.floatleft p { font-style: italic; }
+/* thumbnails */
+div.thumb {
+ margin-bottom: .5em;
+ border-style: solid;
+ border-color: white;
+ width: auto;
+}
+div.thumbinner {
+ border: 1px solid #ccc;
+ padding: 3px !important;
+ background-color: #f9f9f9;
+ font-size: 94%;
+ text-align: center;
+ overflow: hidden;
+}
+html .thumbimage {
+ border: 1px solid #ccc;
+}
+html .thumbcaption {
+ border: none;
+ text-align: left;
+ line-height: 1.4em;
+ padding: 3px !important;
+ font-size: 94%;
+}
+div.magnify {
+ float: right;
+ border: none !important;
+ background: none !important;
+}
+div.magnify a, div.magnify img {
+ display: block;
+ border: none !important;
+ background: none !important;
+}
+div.tright {
+ clear: right;
+ float: right;
+ border-width: .5em 0 .8em 1.4em;
+}
+div.tleft {
+ float: left;
+ clear: left;
+ margin-right: .5em;
+ border-width: .5em 1.4em .8em 0;
+}
+
+.hiddenStructure {
+ display: none;
+ speak: none;
+}
+img.tex {
+ vertical-align: middle;
+}
+span.texhtml {
+ font-family: serif;
+}
+
+/*
+** classes for special content elements like town boxes
+** intended to be referenced directly from the wiki src
+*/
+
+/*
+** User styles
+*/
+/* table standards */
+table.rimage {
+ float: right;
+ position: relative;
+ margin-left: 1em;
+ margin-bottom: 1em;
+ text-align: center;
+}
+.toccolours {
+ border: 1px solid #aaa;
+ background-color: #f9f9f9;
+ padding: 5px;
+ font-size: 95%;
+}
+div.townBox {
+ position: relative;
+ float: right;
+ background: white;
+ margin-left: 1em;
+ border: 1px solid gray;
+ padding: .3em;
+ width: 200px;
+ overflow: hidden;
+ clear: right;
+}
+div.townBox dl {
+ padding: 0;
+ margin: 0 0 .3em;
+ font-size: 96%;
+}
+div.townBox dl dt {
+ background: none;
+ margin: .4em 0 0;
+}
+div.townBox dl dd {
+ margin: .1em 0 0 1.1em;
+ background-color: #f3f3f3;
+}
+
+/*
+** edit views etc
+*/
+.special li {
+ line-height: 1.4em;
+ margin: 0;
+ padding: 0;
+}
+
+/* Page history styling */
+/* the auto-generated edit comments */
+.autocomment {
+ color: gray;
+}
+#pagehistory span.user {
+ margin-left: 1.4em;
+ margin-right: .4em;
+}
+#pagehistory span.minor {
+ font-weight: bold;
+}
+#pagehistory li {
+ border: 1px solid white;
+}
+#pagehistory li.selected {
+ background-color: #f9f9f9;
+ border: 1px dashed #aaa;
+}
+
+/*
+** Diff rendering
+*/
+table.diff, td.diff-otitle, td.diff-ntitle {
+ background-color: white;
+}
+td.diff-addedline {
+ background: #cfc;
+ font-size: smaller;
+}
+td.diff-deletedline {
+ background: #ffa;
+ font-size: smaller;
+}
+td.diff-context {
+ background: #eee;
+ font-size: smaller;
+}
+.diffchange {
+ color: red;
+ font-weight: bold;
+}
+
+/*
+** keep the whitespace in front of the ^=, hides rule from konqueror
+** this is css3, the validator doesn't like it when validating as css2
+*/
+#bodyContent a.external,
+#bodyContent a[href ^="gopher://"] {
+ background: url(external.png) center right no-repeat;
+ padding-right: 13px;
+}
+#bodyContent a[href ^="https://"],
+.link-https {
+ background: url(lock_icon.gif) center right no-repeat;
+ padding-right: 16px;
+}
+#bodyContent a[href ^="mailto:"],
+.link-mailto {
+ background: url(mail_icon.gif) center right no-repeat;
+ padding-right: 18px;
+}
+#bodyContent a[href ^="news://"] {
+ background: url(news_icon.png) center right no-repeat;
+ padding-right: 18px;
+}
+#bodyContent a[href ^="ftp://"],
+.link-ftp {
+ background: url(file_icon.gif) center right no-repeat;
+ padding-right: 18px;
+}
+#bodyContent a[href ^="irc://"],
+.link-irc {
+ background: url(discussionitem_icon.gif) center right no-repeat;
+ padding-right: 18px;
+}
+#bodyContent a.external[href $=".ogg"], #bodyContent a.external[href $=".OGG"],
+#bodyContent a.external[href $=".mid"], #bodyContent a.external[href $=".MID"],
+#bodyContent a.external[href $=".midi"], #bodyContent a.external[href $=".MIDI"],
+#bodyContent a.external[href $=".mp3"], #bodyContent a.external[href $=".MP3"],
+#bodyContent a.external[href $=".wav"], #bodyContent a.external[href $=".WAV"],
+#bodyContent a.external[href $=".wma"], #bodyContent a.external[href $=".WMA"],
+.link-audio {
+ background: url("audio.png") center right no-repeat;
+ padding-right: 13px;
+}
+#bodyContent a.external[href $=".ogm"], #bodyContent a.external[href $=".OGM"],
+#bodyContent a.external[href $=".avi"], #bodyContent a.external[href $=".AVI"],
+#bodyContent a.external[href $=".mpeg"], #bodyContent a.external[href $=".MPEG"],
+#bodyContent a.external[href $=".mpg"], #bodyContent a.external[href $=".MPG"],
+.link-video {
+ background: url("video.png") center right no-repeat;
+ padding-right: 13px;
+}
+#bodyContent a.external[href $=".pdf"], #bodyContent a.external[href $=".PDF"],
+#bodyContent a.external[href *=".pdf#"], #bodyContent a.external[href *=".PDF#"],
+#bodyContent a.external[href *=".pdf?"], #bodyContent a.external[href *=".PDF?"],
+.link-document {
+ background: url("document.png") center right no-repeat;
+ padding-right: 12px;
+}
+
+/* disable interwiki styling */
+#bodyContent a.extiw,
+#bodyContent a.extiw:active {
+ color: #36b;
+ background: none;
+ padding: 0;
+}
+#bodyContent a.external {
+ color: #36b;
+}
+/* this can be used in the content area to switch off
+special external link styling */
+#bodyContent .plainlinks a {
+ background: none !important;
+ padding: 0 !important;
+}
+/*
+** Structural Elements
+*/
+
+/*
+** general portlet styles (elements in the quickbar)
+*/
+.portlet {
+ border: none;
+ margin: 0 0 .5em;
+ padding: 0;
+ float: none;
+ width: 11.6em;
+ overflow: hidden;
+}
+.portlet h4 {
+ font-size: 95%;
+ font-weight: normal;
+ white-space: nowrap;
+}
+.portlet h5 {
+ background: transparent;
+ padding: 0 1em 0 .5em;
+ display: inline;
+ height: 1em;
+ text-transform: lowercase;
+ font-size: 91%;
+ font-weight: normal;
+ white-space: nowrap;
+}
+.portlet h6 {
+ background: #ffae2e;
+ border: 1px solid #2f6fab;
+ border-style: solid solid none solid;
+ padding: 0 1em 0 1em;
+ text-transform: lowercase;
+ display: block;
+ font-size: 1em;
+ height: 1.2em;
+ font-weight: normal;
+ white-space: nowrap;
+}
+.pBody {
+ font-size: 95%;
+ background-color: white;
+ color: black;
+ border-collapse: collapse;
+ border: 1px solid #aaa;
+ padding: 0 .8em .3em .5em;
+}
+.portlet h1,
+.portlet h2,
+.portlet h3,
+.portlet h4 {
+ margin: 0;
+ padding: 0;
+}
+.portlet ul {
+ line-height: 1.5em;
+ list-style-type: square;
+ list-style-image: url(bullet.gif);
+ font-size: 95%;
+}
+.portlet li {
+ padding: 0;
+ margin: 0;
+}
+
+/*
+** Logo properties
+*/
+
+@media handheld {
+ #p-logo { display: none }
+}
+
+/*
+** the navigation portlet
+*/
+
+#p-navigation .pBody {
+ padding-right: 0;
+}
+
+#p-navigation li.active a, #p-navigation li.active a:hover {
+ text-decoration: none;
+ font-weight: bold;
+}
+
+
+/*
+** Search portlet
+*/
+input.searchButton {
+ margin-top: 1px;
+ font-size: 95%;
+}
+#searchGoButton {
+ padding-left: .5em;
+ padding-right: .5em;
+ font-weight: bold;
+}
+#searchInput {
+ width: 10.9em;
+ margin: 0;
+ font-size: 95%;
+}
+#p-search .pBody {
+ padding: .5em .4em .4em .4em;
+ text-align: center;
+}
+
+/*
+** the personal toolbar
+*/
+#p-personal ul {
+ text-transform: lowercase;
+}
+#p-personal li.active {
+ font-weight: bold;
+}
+/*
+** the page-related actions- page/talk, edit etc
+*/
+#p-cactions .hiddenStructure {
+ display: none;
+}
+#p-cactions li a {
+ text-transform: lowercase;
+}
+
+/* TODO: #t-iscite is only used by the Cite extension, come up with some
+ * system which allows extensions to add to this file on the fly
+ */
+#t-ispermalink, #t-iscite {
+ color: #999;
+}
+/*
+** footer
+*/
+#footer {
+ background-color: white;
+ border-top: 1px solid #fabd23;
+ border-bottom: 1px solid #fabd23;
+ margin: .6em 0 1em 0;
+ padding: .4em 0 1.2em 0;
+ text-align: center;
+ font-size: 90%;
+}
+#footer li {
+ display: inline;
+ margin: 0 1.3em;
+}
+/* hide from incapable browsers */
+head:first-child+body #footer li { white-space: nowrap; }
+#f-poweredbyico, #f-copyrightico {
+ margin: 0 8px;
+ position: relative;
+ top: -2px; /* Bump it up just a tad */
+}
+#f-poweredbyico {
+ float: right;
+ height: 1%;
+}
+#f-copyrightico {
+ float: left;
+ height: 1%;
+}
+
+/* js pref toc */
+#preftoc {
+ margin: 0;
+ padding: 0;
+ width: 100%;
+ clear: both;
+}
+#preftoc li {
+ background-color: #f0f0f0;
+ color: #000;
+}
+#preftoc li.selected {
+ font-weight: bold;
+ background-color: #f9f9f9;
+ border: 1px solid #aaa;
+ border-bottom: none;
+ cursor: default;
+ top: 1px;
+ padding-top: 2px;
+ margin-right: -3px;
+}
+#preftoc > li.selected {
+ top: 2px;
+}
+#preftoc a,
+#preftoc a:active {
+ display: block;
+ color: #000;
+ padding: 0 .7em;
+ position: relative;
+ text-decoration: none;
+}
+#preftoc li.selected a {
+ cursor: default;
+ text-decoration: none;
+}
+#prefcontrol {
+ padding-top: 2em;
+ clear: both;
+}
+#preferences {
+ margin: 0;
+ border: 1px solid #aaa;
+ clear: both;
+ padding: 1.5em;
+ background-color: #F9F9F9;
+}
+.prefsection {
+ border: none;
+ padding: 0;
+ margin: 0;
+}
+.prefsection fieldset {
+ border: 1px solid #aaa;
+ float: left;
+ margin-right: 2em;
+}
+.prefsection legend {
+ font-weight: bold;
+}
+.prefsection table, .prefsection legend {
+ background-color: #F9F9F9;
+}
+div.prefsectiontip {
+ font-size: 95%;
+ margin-top: 0;
+ background-color: #FFC1C1;
+ padding: .2em .7em;
+ clear: both;
+}
+.btnSavePrefs {
+ font-weight: bold;
+ padding-left: .3em;
+ padding-right: .3em;
+}
+
+.preferences-login {
+ clear: both;
+ margin-bottom: 1.5em;
+}
+
+.prefcache {
+ font-size: 90%;
+ margin-top: 2em;
+}
+
+div#userloginForm form,
+div#userlogin form#userlogin2 {
+ margin: 0 3em 1em 0;
+ border: 1px solid #aaa;
+ clear: both;
+ padding: 1.5em 2em;
+ background-color: #f9f9f9;
+ float: left;
+}
+
+div#userloginForm table,
+div#userlogin form#userlogin2 table {
+ background-color: #f9f9f9;
+}
+
+div#userloginForm h2,
+div#userlogin form#userlogin2 h2 {
+ padding-top: 0;
+}
+
+div#userlogin .captcha {
+ border: 1px solid #bbb;
+ padding: 1.5em 2em;
+ width: 400px;
+ background-color: white;
+}
+
+
+#userloginprompt, #languagelinks {
+ font-size: 85%;
+}
+
+#login-sectiontip {
+ font-size: 85%;
+ line-height: 1.2;
+ padding-top: 2em;
+}
+
+#userlogin .loginText, #userlogin .loginPassword {
+ width: 12em;
+}
+
+#userloginlink a, #wpLoginattempt, #wpCreateaccount {
+ font-weight: bold;
+}
+
+/* more IE fixes */
+/* float/negative margin brokenness */
+* html #footer {margin-top: 0;}
+* html #column-content {
+ display: inline;
+ margin-bottom: 0;
+}
+* html div.editsection { font-size: smaller; }
+#pagehistory li.selected { position: relative; }
+
+/* Mac IE 5.0 fix; floated content turns invisible */
+* > html #column-content {
+ float: none;
+}
+* > html #column-one {
+ position: absolute;
+ left: 0;
+ top: 0;
+}
+* > html #footer {
+ margin-left: 13.2em;
+}
+.redirectText {
+ font-size: 150%;
+ margin: 5px;
+}
+
+.printfooter {
+ display: none;
+}
+
+.not-patrolled {
+ background-color: #ffa;
+}
+div.patrollink {
+ font-size: 75%;
+ text-align: right;
+}
+span.newpage, span.minor, span.searchmatch, span.bot {
+ font-weight: bold;
+}
+span.unpatrolled {
+ font-weight: bold;
+ color: red;
+}
+
+span.searchmatch {
+ color: red;
+}
+.sharedUploadNotice {
+ font-style: italic;
+}
+
+span.updatedmarker {
+ color: black;
+ background-color: #0f0;
+}
+
+table.gallery {
+ border: 1px solid #ccc;
+ margin: 2px;
+ padding: 2px;
+ background-color: white;
+}
+
+table.gallery tr {
+ vertical-align: top;
+}
+
+table.gallery td {
+ vertical-align: top;
+ background-color: #f9f9f9;
+ border: solid 2px white;
+}
+
+/* Keep this temporarily so that cached pages will display right */
+table.gallery td.galleryheader {
+ text-align: center;
+ font-weight: bold;
+}
+table.gallery caption {
+ font-weight: bold;
+}
+
+div.gallerybox {
+ margin: 2px;
+ width: 150px;
+}
+
+div.gallerybox div.thumb {
+ text-align: center;
+ border: 1px solid #ccc;
+ margin: 2px;
+}
+
+div.gallerytext {
+ font-size: 94%;
+ padding: 2px 4px;
+}
+
+span.comment {
+ font-style: italic;
+}
+
+span.changedby {
+ font-size: 95%;
+}
+
+.previewnote {
+ text-indent: 3em;
+ color: #c00;
+ border-bottom: 1px solid #aaa;
+ padding-bottom: 1em;
+ margin-bottom: 1em;
+}
+
+.previewnote p {
+ margin: 0;
+ padding: 0;
+}
+
+.editExternally {
+ border: 1px solid gray;
+ background-color: #ffffff;
+ padding: 3px;
+ margin-top: 0.5em;
+ float: left;
+ font-size: small;
+ text-align: center;
+}
+.editExternallyHelp {
+ font-style: italic;
+ color: gray;
+}
+
+li span.deleted, span.history-deleted {
+ text-decoration: line-through;
+ color: #888;
+ font-style: italic;
+}
+
+.toggle {
+ margin-left: 2em;
+ text-indent: -2em;
+}
+
+/* Classes for EXIF data display */
+table.mw_metadata {
+ font-size: 0.8em;
+ margin-left: 0.5em;
+ margin-bottom: 0.5em;
+ width: 300px;
+}
+
+table.mw_metadata caption {
+ font-weight: bold;
+}
+
+table.mw_metadata th {
+ font-weight: normal;
+}
+
+table.mw_metadata td {
+ padding: 0.1em;
+}
+
+table.mw_metadata {
+ border: none;
+ border-collapse: collapse;
+}
+
+table.mw_metadata td, table.mw_metadata th {
+ text-align: center;
+ border: 1px solid #aaaaaa;
+ padding-left: 0.1em;
+ padding-right: 0.1em;
+}
+
+table.mw_metadata th {
+ background-color: #f9f9f9;
+}
+
+table.mw_metadata td {
+ background-color: #fcfcfc;
+}
+
+table.collapsed tr.collapsable {
+ display: none;
+}
+
+
+/* filetoc */
+ul#filetoc {
+ text-align: center;
+ border: 1px solid #aaaaaa;
+ background-color: #f9f9f9;
+ padding: 5px;
+ font-size: 95%;
+ margin-bottom: 0.5em;
+ margin-left: 0;
+ margin-right: 0;
+}
+
+#filetoc li {
+ display: inline;
+ list-style-type: none;
+ padding-right: 2em;
+}
+
+input#wpSummary {
+ width: 80%;
+}
+
+/* @bug 1714 */
+input#wpSave, input#wpDiff {
+ margin-right: 0.33em;
+}
+
+#editform .editOptions {
+ display: inline;
+}
+
+#wpSave {
+ font-weight: bold;
+}
+
+/* Classes for article validation */
+
+table.revisionform_default {
+ border: 1px solid #000000;
+}
+
+table.revisionform_focus {
+ border: 1px solid #000000;
+ background-color:#00BBFF;
+}
+
+tr.revision_tr_default {
+ background-color:#EEEEEE;
+}
+
+tr.revision_tr_first {
+ background-color:#DDDDDD;
+}
+
+p.revision_saved {
+ color: green;
+ font-weight:bold;
+}
+
+#mw_trackbacks {
+ border: solid 1px #bbbbff;
+ background-color: #eeeeff;
+ padding: 0.2em;
+}
+
+
+/* Allmessages table */
+
+#allmessagestable th {
+ background-color: #b2b2ff;
+}
+
+#allmessagestable tr.orig {
+ background-color: #ffe2e2;
+}
+
+#allmessagestable tr.new {
+ background-color: #e2ffe2;
+}
+
+#allmessagestable tr.def {
+ background-color: #f0f0ff;
+}
+
+
+/* noarticletext */
+div.noarticletext {
+ border: 1px solid #ccc;
+ background: #fff;
+ padding: .2em 1em;
+ color: #000;
+}
+
+div#searchTargetContainer {
+ left: 10px;
+ top: 10px;
+ width: 90%;
+ background: white;
+}
+
+div#searchTarget {
+ padding: 3px;
+ margin: 5px;
+ background: #F0F0F0;
+ border: solid 1px blue;
+}
+
+div#searchTarget ul li {
+ list-style: none;
+}
+
+div#searchTarget ul li:before {
+ color: orange;
+ content: "\00BB \0020";
+}
+
+div.multipageimagenavbox {
+ border: solid 1px silver;
+ padding: 4px;
+ margin: 1em;
+ -moz-border-radius: 6px;
+ background: #f0f0f0;
+}
+
+div.multipageimagenavbox div.thumb {
+ border: none;
+ margin-left: 2em;
+ margin-right: 2em;
+}
+
+div.multipageimagenavbox hr {
+ margin: 6px;
+}
+
+table.multipageimage td {
+ text-align: center;
+}
+
+/** Special:Version */
+
+table#sv-ext, table#sv-hooks {
+ margin: 1em;
+ padding:0em;
+}
+
+#sv-ext td, #sv-hooks td,
+#sv-ext th, #sv-hooks th {
+ border: 1px solid #A0A0A0;
+ padding: 0 0.15em 0 0.15em;
+}
+#sv-ext th, #sv-hooks th {
+ background-color: #F0F0F0;
+ color: black;
+ padding: 0 0.15em 0 0.15em;
+}
+tr.sv-space{
+ height: 0.8em;
+ border:none;
+}
+tr.sv-space td { display: none; }
+
+/*
+ Table pager (e.g. Special:Imagelist)
+ - remove underlines from the navigation link
+ - collapse borders
+ - set the borders to outsets (similar to Special:Allmessages)
+ - remove line wrapping for all td and th, set background color
+ - restore line wrapping for the last two table cells (description and size)
+*/
+.TablePager_nav a { text-decoration: none; }
+.TablePager { border-collapse: collapse; }
+.TablePager, .TablePager td, .TablePager th {
+ border: 0.15em solid #777777;
+ padding: 0 0.15em 0 0.15em;
+}
+.TablePager th { background-color: #eeeeff }
+.TablePager td { background-color: #ffffff }
+.TablePager tr:hover td { background-color: #eeeeff }
+
+.imagelist td, .imagelist th { white-space: nowrap }
+.imagelist .TablePager_col_links { background-color: #eeeeff }
+.imagelist .TablePager_col_img_description { white-space: normal }
+.imagelist th.TablePager_sort { background-color: #ccccff }
+
+.templatesUsed { margin-top: 1.5em; }
+
+.mw-summary-preview {
+ margin: 0.1em 0;
+}
+@media handheld {
+ .nonessential {
+ /* Kill big bulky stuff that will clog up the screen */
+ display: none;
+ }
+}
+
+/**
+ * Here is some stuff that's ACTUALLY COMMON TO ALL SKINS.
+ * When the day comes, it can be moved to a *real* common.css.
+ */
+.mw-plusminus-null { color: #aaa; }
+.texvc { direction: ltr; unicode-bidi: embed; }
+/* Stop floats from intruding into edit area in previews */
+#toolbar, #wpTextbox1 { clear: both; } \ No newline at end of file
diff --git a/pyyaml/YAMLish_files/index.js b/pyyaml/YAMLish_files/index.js
new file mode 100644
index 0000000..42c9619
--- /dev/null
+++ b/pyyaml/YAMLish_files/index.js
@@ -0,0 +1,9 @@
+/* generated javascript */
+var skin = 'monobook';
+var stylepath = '/wiki/skins';
+
+/* MediaWiki:Common.js */
+/* Any JavaScript here will be loaded for all users on every page load. */
+
+/* MediaWiki:Monobook.js (deprecated; migrate to Common.js!) */
+/* Deprecated; use [[MediaWiki:common.js]] */ \ No newline at end of file
diff --git a/pyyaml/YAMLish_files/poweredby_mediawiki_88x31.png b/pyyaml/YAMLish_files/poweredby_mediawiki_88x31.png
new file mode 100644
index 0000000..ce1765d
--- /dev/null
+++ b/pyyaml/YAMLish_files/poweredby_mediawiki_88x31.png
Binary files differ
diff --git a/pyyaml/YAMLish_files/wikibits.js b/pyyaml/YAMLish_files/wikibits.js
new file mode 100644
index 0000000..6299e5f
--- /dev/null
+++ b/pyyaml/YAMLish_files/wikibits.js
@@ -0,0 +1,1246 @@
+// MediaWiki JavaScript support functions
+
+var clientPC = navigator.userAgent.toLowerCase(); // Get client info
+var is_gecko = ((clientPC.indexOf('gecko')!=-1) && (clientPC.indexOf('spoofer')==-1)
+ && (clientPC.indexOf('khtml') == -1) && (clientPC.indexOf('netscape/7.0')==-1));
+var is_safari = ((clientPC.indexOf('applewebkit')!=-1) && (clientPC.indexOf('spoofer')==-1));
+var is_khtml = (navigator.vendor == 'KDE' || ( document.childNodes && !document.all && !navigator.taintEnabled ));
+// For accesskeys
+var is_ff2_win = (clientPC.indexOf('firefox/2')!=-1 || clientPC.indexOf('minefield/3')!=-1) && clientPC.indexOf('windows')!=-1;
+var is_ff2_x11 = (clientPC.indexOf('firefox/2')!=-1 || clientPC.indexOf('minefield/3')!=-1) && clientPC.indexOf('x11')!=-1;
+if (clientPC.indexOf('opera') != -1) {
+ var is_opera = true;
+ var is_opera_preseven = (window.opera && !document.childNodes);
+ var is_opera_seven = (window.opera && document.childNodes);
+}
+
+// Global external objects used by this script.
+/*extern ta, stylepath, skin */
+
+// add any onload functions in this hook (please don't hard-code any events in the xhtml source)
+var doneOnloadHook;
+
+if (!window.onloadFuncts) {
+ var onloadFuncts = [];
+}
+
+function addOnloadHook(hookFunct) {
+ // Allows add-on scripts to add onload functions
+ onloadFuncts[onloadFuncts.length] = hookFunct;
+}
+
+function hookEvent(hookName, hookFunct) {
+ if (window.addEventListener) {
+ window.addEventListener(hookName, hookFunct, false);
+ } else if (window.attachEvent) {
+ window.attachEvent("on" + hookName, hookFunct);
+ }
+}
+
+// document.write special stylesheet links
+if (typeof stylepath != 'undefined' && typeof skin != 'undefined') {
+ if (is_opera_preseven) {
+ document.write('<link rel="stylesheet" type="text/css" href="'+stylepath+'/'+skin+'/Opera6Fixes.css">');
+ } else if (is_opera_seven) {
+ document.write('<link rel="stylesheet" type="text/css" href="'+stylepath+'/'+skin+'/Opera7Fixes.css">');
+ } else if (is_khtml) {
+ document.write('<link rel="stylesheet" type="text/css" href="'+stylepath+'/'+skin+'/KHTMLFixes.css">');
+ }
+}
+
+if (wgBreakFrames) {
+ // Un-trap us from framesets
+ if (window.top != window) {
+ window.top.location = window.location;
+ }
+}
+
+// for enhanced RecentChanges
+function toggleVisibility(_levelId, _otherId, _linkId) {
+ var thisLevel = document.getElementById(_levelId);
+ var otherLevel = document.getElementById(_otherId);
+ var linkLevel = document.getElementById(_linkId);
+ if (thisLevel.style.display == 'none') {
+ thisLevel.style.display = 'block';
+ otherLevel.style.display = 'none';
+ linkLevel.style.display = 'inline';
+ } else {
+ thisLevel.style.display = 'none';
+ otherLevel.style.display = 'inline';
+ linkLevel.style.display = 'none';
+ }
+}
+
+function historyRadios(parent) {
+ var inputs = parent.getElementsByTagName('input');
+ var radios = [];
+ for (var i = 0; i < inputs.length; i++) {
+ if (inputs[i].name == "diff" || inputs[i].name == "oldid") {
+ radios[radios.length] = inputs[i];
+ }
+ }
+ return radios;
+}
+
+// check selection and tweak visibility/class onclick
+function diffcheck() {
+ var dli = false; // the li where the diff radio is checked
+ var oli = false; // the li where the oldid radio is checked
+ var hf = document.getElementById('pagehistory');
+ if (!hf) {
+ return true;
+ }
+ var lis = hf.getElementsByTagName('li');
+ for (var i=0;i<lis.length;i++) {
+ var inputs = historyRadios(lis[i]);
+ if (inputs[1] && inputs[0]) {
+ if (inputs[1].checked || inputs[0].checked) { // this row has a checked radio button
+ if (inputs[1].checked && inputs[0].checked && inputs[0].value == inputs[1].value) {
+ return false;
+ }
+ if (oli) { // it's the second checked radio
+ if (inputs[1].checked) {
+ oli.className = "selected";
+ return false;
+ }
+ } else if (inputs[0].checked) {
+ return false;
+ }
+ if (inputs[0].checked) {
+ dli = lis[i];
+ }
+ if (!oli) {
+ inputs[0].style.visibility = 'hidden';
+ }
+ if (dli) {
+ inputs[1].style.visibility = 'hidden';
+ }
+ lis[i].className = "selected";
+ oli = lis[i];
+ } else { // no radio is checked in this row
+ if (!oli) {
+ inputs[0].style.visibility = 'hidden';
+ } else {
+ inputs[0].style.visibility = 'visible';
+ }
+ if (dli) {
+ inputs[1].style.visibility = 'hidden';
+ } else {
+ inputs[1].style.visibility = 'visible';
+ }
+ lis[i].className = "";
+ }
+ }
+ }
+ return true;
+}
+
+// page history stuff
+// attach event handlers to the input elements on history page
+function histrowinit() {
+ var hf = document.getElementById('pagehistory');
+ if (!hf) {
+ return;
+ }
+ var lis = hf.getElementsByTagName('li');
+ for (var i = 0; i < lis.length; i++) {
+ var inputs = historyRadios(lis[i]);
+ if (inputs[0] && inputs[1]) {
+ inputs[0].onclick = diffcheck;
+ inputs[1].onclick = diffcheck;
+ }
+ }
+ diffcheck();
+}
+
+// generate toc from prefs form, fold sections
+// XXX: needs testing on IE/Mac and safari
+// more comments to follow
+function tabbedprefs() {
+ var prefform = document.getElementById('preferences');
+ if (!prefform || !document.createElement) {
+ return;
+ }
+ if (prefform.nodeName.toLowerCase() == 'a') {
+ return; // Occasional IE problem
+ }
+ prefform.className = prefform.className + 'jsprefs';
+ var sections = [];
+ var children = prefform.childNodes;
+ var seci = 0;
+ for (var i = 0; i < children.length; i++) {
+ if (children[i].nodeName.toLowerCase() == 'fieldset') {
+ children[i].id = 'prefsection-' + seci;
+ children[i].className = 'prefsection';
+ if (is_opera || is_khtml) {
+ children[i].className = 'prefsection operaprefsection';
+ }
+ var legends = children[i].getElementsByTagName('legend');
+ sections[seci] = {};
+ legends[0].className = 'mainLegend';
+ if (legends[0] && legends[0].firstChild.nodeValue) {
+ sections[seci].text = legends[0].firstChild.nodeValue;
+ } else {
+ sections[seci].text = '# ' + seci;
+ }
+ sections[seci].secid = children[i].id;
+ seci++;
+ if (sections.length != 1) {
+ children[i].style.display = 'none';
+ } else {
+ var selectedid = children[i].id;
+ }
+ }
+ }
+ var toc = document.createElement('ul');
+ toc.id = 'preftoc';
+ toc.selectedid = selectedid;
+ for (i = 0; i < sections.length; i++) {
+ var li = document.createElement('li');
+ if (i === 0) {
+ li.className = 'selected';
+ }
+ var a = document.createElement('a');
+ a.href = '#' + sections[i].secid;
+ a.onmousedown = a.onclick = uncoversection;
+ a.appendChild(document.createTextNode(sections[i].text));
+ a.secid = sections[i].secid;
+ li.appendChild(a);
+ toc.appendChild(li);
+ }
+ prefform.parentNode.insertBefore(toc, prefform.parentNode.childNodes[0]);
+ document.getElementById('prefsubmit').id = 'prefcontrol';
+}
+
+function uncoversection() {
+ var oldsecid = this.parentNode.parentNode.selectedid;
+ var newsec = document.getElementById(this.secid);
+ if (oldsecid != this.secid) {
+ var ul = document.getElementById('preftoc');
+ document.getElementById(oldsecid).style.display = 'none';
+ newsec.style.display = 'block';
+ ul.selectedid = this.secid;
+ var lis = ul.getElementsByTagName('li');
+ for (var i = 0; i< lis.length; i++) {
+ lis[i].className = '';
+ }
+ this.parentNode.className = 'selected';
+ }
+ return false;
+}
+
+// Timezone stuff
+// tz in format [+-]HHMM
+function checkTimezone(tz, msg) {
+ var localclock = new Date();
+ // returns negative offset from GMT in minutes
+ var tzRaw = localclock.getTimezoneOffset();
+ var tzHour = Math.floor( Math.abs(tzRaw) / 60);
+ var tzMin = Math.abs(tzRaw) % 60;
+ var tzString = ((tzRaw >= 0) ? "-" : "+") + ((tzHour < 10) ? "0" : "") + tzHour + ((tzMin < 10) ? "0" : "") + tzMin;
+ if (tz != tzString) {
+ var junk = msg.split('$1');
+ document.write(junk[0] + "UTC" + tzString + junk[1]);
+ }
+}
+
+function unhidetzbutton() {
+ var tzb = document.getElementById('guesstimezonebutton');
+ if (tzb) {
+ tzb.style.display = 'inline';
+ }
+}
+
+// in [-]HH:MM format...
+// won't yet work with non-even tzs
+function fetchTimezone() {
+ // FIXME: work around Safari bug
+ var localclock = new Date();
+ // returns negative offset from GMT in minutes
+ var tzRaw = localclock.getTimezoneOffset();
+ var tzHour = Math.floor( Math.abs(tzRaw) / 60);
+ var tzMin = Math.abs(tzRaw) % 60;
+ var tzString = ((tzRaw >= 0) ? "-" : "") + ((tzHour < 10) ? "0" : "") + tzHour +
+ ":" + ((tzMin < 10) ? "0" : "") + tzMin;
+ return tzString;
+}
+
+function guessTimezone(box) {
+ document.getElementsByName("wpHourDiff")[0].value = fetchTimezone();
+}
+
+function showTocToggle() {
+ if (document.createTextNode) {
+ // Uses DOM calls to avoid document.write + XHTML issues
+
+ var linkHolder = document.getElementById('toctitle');
+ if (!linkHolder) {
+ return;
+ }
+
+ var outerSpan = document.createElement('span');
+ outerSpan.className = 'toctoggle';
+
+ var toggleLink = document.createElement('a');
+ toggleLink.id = 'togglelink';
+ toggleLink.className = 'internal';
+ toggleLink.href = 'javascript:toggleToc()';
+ toggleLink.appendChild(document.createTextNode(tocHideText));
+
+ outerSpan.appendChild(document.createTextNode('['));
+ outerSpan.appendChild(toggleLink);
+ outerSpan.appendChild(document.createTextNode(']'));
+
+ linkHolder.appendChild(document.createTextNode(' '));
+ linkHolder.appendChild(outerSpan);
+
+ var cookiePos = document.cookie.indexOf("hidetoc=");
+ if (cookiePos > -1 && document.cookie.charAt(cookiePos + 8) == 1) {
+ toggleToc();
+ }
+ }
+}
+
+function changeText(el, newText) {
+ // Safari work around
+ if (el.innerText) {
+ el.innerText = newText;
+ } else if (el.firstChild && el.firstChild.nodeValue) {
+ el.firstChild.nodeValue = newText;
+ }
+}
+
+function toggleToc() {
+ var toc = document.getElementById('toc').getElementsByTagName('ul')[0];
+ var toggleLink = document.getElementById('togglelink');
+
+ if (toc && toggleLink && toc.style.display == 'none') {
+ changeText(toggleLink, tocHideText);
+ toc.style.display = 'block';
+ document.cookie = "hidetoc=0";
+ } else {
+ changeText(toggleLink, tocShowText);
+ toc.style.display = 'none';
+ document.cookie = "hidetoc=1";
+ }
+}
+
+var mwEditButtons = [];
+var mwCustomEditButtons = []; // eg to add in MediaWiki:Common.js
+
+// this function generates the actual toolbar buttons with localized text
+// we use it to avoid creating the toolbar where javascript is not enabled
+function addButton(imageFile, speedTip, tagOpen, tagClose, sampleText, imageId) {
+ // Don't generate buttons for browsers which don't fully
+ // support it.
+ mwEditButtons[mwEditButtons.length] =
+ {"imageId": imageId,
+ "imageFile": imageFile,
+ "speedTip": speedTip,
+ "tagOpen": tagOpen,
+ "tagClose": tagClose,
+ "sampleText": sampleText};
+}
+
+// this function generates the actual toolbar buttons with localized text
+// we use it to avoid creating the toolbar where javascript is not enabled
+function mwInsertEditButton(parent, item) {
+ var image = document.createElement("img");
+ image.width = 23;
+ image.height = 22;
+ image.className = "mw-toolbar-editbutton";
+ if (item.imageId) image.id = item.imageId;
+ image.src = item.imageFile;
+ image.border = 0;
+ image.alt = item.speedTip;
+ image.title = item.speedTip;
+ image.style.cursor = "pointer";
+ image.onclick = function() {
+ insertTags(item.tagOpen, item.tagClose, item.sampleText);
+ return false;
+ };
+
+ parent.appendChild(image);
+ return true;
+}
+
+function mwSetupToolbar() {
+ var toolbar = document.getElementById('toolbar');
+ if (!toolbar) { return false; }
+
+ var textbox = document.getElementById('wpTextbox1');
+ if (!textbox) { return false; }
+
+ // Don't generate buttons for browsers which don't fully
+ // support it.
+ if (!document.selection && textbox.selectionStart === null) {
+ return false;
+ }
+
+ for (var i = 0; i < mwEditButtons.length; i++) {
+ mwInsertEditButton(toolbar, mwEditButtons[i]);
+ }
+ for (var i = 0; i < mwCustomEditButtons.length; i++) {
+ mwInsertEditButton(toolbar, mwCustomEditButtons[i]);
+ }
+ return true;
+}
+
+function escapeQuotes(text) {
+ var re = new RegExp("'","g");
+ text = text.replace(re,"\\'");
+ re = new RegExp("\\n","g");
+ text = text.replace(re,"\\n");
+ return escapeQuotesHTML(text);
+}
+
+function escapeQuotesHTML(text) {
+ var re = new RegExp('&',"g");
+ text = text.replace(re,"&amp;");
+ re = new RegExp('"',"g");
+ text = text.replace(re,"&quot;");
+ re = new RegExp('<',"g");
+ text = text.replace(re,"&lt;");
+ re = new RegExp('>',"g");
+ text = text.replace(re,"&gt;");
+ return text;
+}
+
+// apply tagOpen/tagClose to selection in textarea,
+// use sampleText instead of selection if there is none
+// copied and adapted from phpBB
+function insertTags(tagOpen, tagClose, sampleText) {
+ var txtarea;
+ if (document.editform) {
+ txtarea = document.editform.wpTextbox1;
+ } else {
+ // some alternate form? take the first one we can find
+ var areas = document.getElementsByTagName('textarea');
+ txtarea = areas[0];
+ }
+
+ // IE
+ if (document.selection && !is_gecko) {
+ var theSelection = document.selection.createRange().text;
+ if (!theSelection) {
+ theSelection=sampleText;
+ }
+ txtarea.focus();
+ if (theSelection.charAt(theSelection.length - 1) == " ") { // exclude ending space char, if any
+ theSelection = theSelection.substring(0, theSelection.length - 1);
+ document.selection.createRange().text = tagOpen + theSelection + tagClose + " ";
+ } else {
+ document.selection.createRange().text = tagOpen + theSelection + tagClose;
+ }
+
+ // Mozilla
+ } else if(txtarea.selectionStart || txtarea.selectionStart == '0') {
+ var replaced = false;
+ var startPos = txtarea.selectionStart;
+ var endPos = txtarea.selectionEnd;
+ if (endPos-startPos) {
+ replaced = true;
+ }
+ var scrollTop = txtarea.scrollTop;
+ var myText = (txtarea.value).substring(startPos, endPos);
+ if (!myText) {
+ myText=sampleText;
+ }
+ var subst;
+ if (myText.charAt(myText.length - 1) == " ") { // exclude ending space char, if any
+ subst = tagOpen + myText.substring(0, (myText.length - 1)) + tagClose + " ";
+ } else {
+ subst = tagOpen + myText + tagClose;
+ }
+ txtarea.value = txtarea.value.substring(0, startPos) + subst +
+ txtarea.value.substring(endPos, txtarea.value.length);
+ txtarea.focus();
+ //set new selection
+ if (replaced) {
+ var cPos = startPos+(tagOpen.length+myText.length+tagClose.length);
+ txtarea.selectionStart = cPos;
+ txtarea.selectionEnd = cPos;
+ } else {
+ txtarea.selectionStart = startPos+tagOpen.length;
+ txtarea.selectionEnd = startPos+tagOpen.length+myText.length;
+ }
+ txtarea.scrollTop = scrollTop;
+
+ // All other browsers get no toolbar.
+ // There was previously support for a crippled "help"
+ // bar, but that caused more problems than it solved.
+ }
+ // reposition cursor if possible
+ if (txtarea.createTextRange) {
+ txtarea.caretPos = document.selection.createRange().duplicate();
+ }
+}
+
+
+/**
+ * Set the accesskey prefix based on browser detection.
+ */
+var tooltipAccessKeyPrefix = 'alt-';
+if (is_opera) {
+ tooltipAccessKeyPrefix = 'shift-esc-';
+} else if (is_safari
+ || navigator.userAgent.toLowerCase().indexOf('mac') != -1
+ || navigator.userAgent.toLowerCase().indexOf('konqueror') != -1 ) {
+ tooltipAccessKeyPrefix = 'ctrl-';
+} else if (is_ff2_x11 || is_ff2_win) {
+ tooltipAccessKeyPrefix = 'alt-shift-';
+}
+var tooltipAccessKeyRegexp = /\[(ctrl-)?(alt-)?(shift-)?(esc-)?.\]$/;
+
+/**
+ * Add the appropriate prefix to the accesskey shown in the tooltip.
+ * If the nodeList parameter is given, only those nodes are updated;
+ * otherwise, all the nodes that will probably have accesskeys by
+ * default are updated.
+ *
+ * @param Array nodeList -- list of elements to update
+ */
+function updateTooltipAccessKeys( nodeList ) {
+ if ( !nodeList ) {
+ // skins without a "column-one" element don't seem to have links with accesskeys either
+ var columnOne = document.getElementById("column-one");
+ if ( columnOne )
+ updateTooltipAccessKeys( columnOne.getElementsByTagName("a") );
+ // these are rare enough that no such optimization is needed
+ updateTooltipAccessKeys( document.getElementsByTagName("input") );
+ updateTooltipAccessKeys( document.getElementsByTagName("label") );
+ return;
+ }
+
+ for ( var i = 0; i < nodeList.length; i++ ) {
+ var element = nodeList[i];
+ var tip = element.getAttribute("title");
+ var key = element.getAttribute("accesskey");
+ if ( key && tooltipAccessKeyRegexp.exec(tip) ) {
+ tip = tip.replace(tooltipAccessKeyRegexp,
+ "["+tooltipAccessKeyPrefix+key+"]");
+ element.setAttribute("title", tip );
+ }
+ }
+}
+
+/**
+ * Add a link to one of the portlet menus on the page, including:
+ *
+ * p-cactions: Content actions (shown as tabs above the main content in Monobook)
+ * p-personal: Personal tools (shown at the top right of the page in Monobook)
+ * p-navigation: Navigation
+ * p-tb: Toolbox
+ *
+ * This function exists for the convenience of custom JS authors. All
+ * but the first three parameters are optional, though providing at
+ * least an id and a tooltip is recommended.
+ *
+ * By default the new link will be added to the end of the list. To
+ * add the link before a given existing item, pass the DOM node of
+ * that item (easily obtained with document.getElementById()) as the
+ * nextnode parameter; to add the link _after_ an existing item, pass
+ * the node's nextSibling instead.
+ *
+ * @param String portlet -- id of the target portlet ("p-cactions", "p-personal", "p-navigation" or "p-tb")
+ * @param String href -- link URL
+ * @param String text -- link text (will be automatically lowercased by CSS for p-cactions in Monobook)
+ * @param String id -- id of the new item, should be unique and preferably have the appropriate prefix ("ca-", "pt-", "n-" or "t-")
+ * @param String tooltip -- text to show when hovering over the link, without accesskey suffix
+ * @param String accesskey -- accesskey to activate this link (one character, try to avoid conflicts)
+ * @param Node nextnode -- the DOM node before which the new item should be added, should be another item in the same list
+ *
+ * @return Node -- the DOM node of the new item (an LI element) or null
+ */
+function addPortletLink(portlet, href, text, id, tooltip, accesskey, nextnode) {
+ var node = document.getElementById(portlet);
+ if ( !node ) return null;
+ node = node.getElementsByTagName( "ul" )[0];
+ if ( !node ) return null;
+
+ var link = document.createElement( "a" );
+ link.appendChild( document.createTextNode( text ) );
+ link.href = href;
+
+ var item = document.createElement( "li" );
+ item.appendChild( link );
+ if ( id ) item.id = id;
+
+ if ( accesskey ) {
+ link.setAttribute( "accesskey", accesskey );
+ tooltip += " ["+accesskey+"]";
+ }
+ if ( tooltip ) {
+ link.setAttribute( "title", tooltip );
+ }
+ if ( accesskey && tooltip ) {
+ updateTooltipAccessKeys( new Array( link ) );
+ }
+
+ if ( nextnode && nextnode.parentNode == node )
+ node.insertBefore( item, nextnode );
+ else
+ node.appendChild( item ); // IE compatibility (?)
+
+ return item;
+}
+
+
+/**
+ * Set up accesskeys/tooltips from the deprecated ta array. If doId
+ * is specified, only set up for that id. Note that this function is
+ * deprecated and will not be supported indefinitely -- use
+ * updateTooltipAccessKey() instead.
+ *
+ * @param mixed doId string or null
+ */
+function akeytt( doId ) {
+ // A lot of user scripts (and some of the code below) break if
+ // ta isn't defined, so we make sure it is. Explictly using
+ // window.ta avoids a "ta is not defined" error.
+ if (!window.ta) window.ta = new Array;
+
+ // Make a local, possibly restricted, copy to avoid clobbering
+ // the original.
+ var ta;
+ if ( doId ) {
+ ta = new Array;
+ ta[doId] = window.ta[doId];
+ } else {
+ ta = window.ta;
+ }
+
+ // Now deal with evil deprecated ta
+ var watchCheckboxExists = document.getElementById( 'wpWatchthis' ) ? true : false;
+ for (var id in ta) {
+ var n = document.getElementById(id);
+ if (n) {
+ var a = null;
+ var ak = '';
+ // Are we putting accesskey in it
+ if (ta[id][0].length > 0) {
+ // Is this object a object? If not assume it's the next child.
+
+ if (n.nodeName.toLowerCase() == "a") {
+ a = n;
+ } else {
+ a = n.childNodes[0];
+ }
+ // Don't add an accesskey for the watch tab if the watch
+ // checkbox is also available.
+ if (a && ((id != 'ca-watch' && id != 'ca-unwatch') || !watchCheckboxExists)) {
+ a.accessKey = ta[id][0];
+ ak = ' ['+tooltipAccessKeyPrefix+ta[id][0]+']';
+ }
+ } else {
+ // We don't care what type the object is when assigning tooltip
+ a = n;
+ ak = '';
+ }
+
+ if (a) {
+ a.title = ta[id][1]+ak;
+ }
+ }
+ }
+}
+
+function setupRightClickEdit() {
+ if (document.getElementsByTagName) {
+ var spans = document.getElementsByTagName('span');
+ for (var i = 0; i < spans.length; i++) {
+ var el = spans[i];
+ if(el.className == 'editsection') {
+ addRightClickEditHandler(el);
+ }
+ }
+ }
+}
+
+function addRightClickEditHandler(el) {
+ for (var i = 0; i < el.childNodes.length; i++) {
+ var link = el.childNodes[i];
+ if (link.nodeType == 1 && link.nodeName.toLowerCase() == 'a') {
+ var editHref = link.getAttribute('href');
+ // find the enclosing (parent) header
+ var prev = el.parentNode;
+ if (prev && prev.nodeType == 1 &&
+ prev.nodeName.match(/^[Hh][1-6]$/)) {
+ prev.oncontextmenu = function(e) {
+ if (!e) { e = window.event; }
+ // e is now the event in all browsers
+ var targ;
+ if (e.target) { targ = e.target; }
+ else if (e.srcElement) { targ = e.srcElement; }
+ if (targ.nodeType == 3) { // defeat Safari bug
+ targ = targ.parentNode;
+ }
+ // targ is now the target element
+
+ // We don't want to deprive the noble reader of a context menu
+ // for the section edit link, do we? (Might want to extend this
+ // to all <a>'s?)
+ if (targ.nodeName.toLowerCase() != 'a'
+ || targ.parentNode.className != 'editsection') {
+ document.location = editHref;
+ return false;
+ }
+ return true;
+ };
+ }
+ }
+ }
+}
+
+var checkboxes;
+var lastCheckbox;
+
+function setupCheckboxShiftClick() {
+ checkboxes = [];
+ lastCheckbox = null;
+ var inputs = document.getElementsByTagName('input');
+ addCheckboxClickHandlers(inputs);
+}
+
+function addCheckboxClickHandlers(inputs, start) {
+ if ( !start) start = 0;
+
+ var finish = start + 250;
+ if ( finish > inputs.length )
+ finish = inputs.length;
+
+ for ( var i = start; i < finish; i++ ) {
+ var cb = inputs[i];
+ if ( !cb.type || cb.type.toLowerCase() != 'checkbox' )
+ continue;
+ cb.index = checkboxes.push(cb) - 1;
+ cb.onmouseup = checkboxMouseupHandler;
+ }
+
+ if ( finish < inputs.length ) {
+ setTimeout( function () {
+ addCheckboxClickHandlers(inputs, finish);
+ }, 200 );
+ }
+}
+
+function checkboxMouseupHandler(e) {
+ if (typeof e == 'undefined') {
+ e = window.event;
+ }
+ if ( !e.shiftKey || lastCheckbox === null ) {
+ lastCheckbox = this.index;
+ return true;
+ }
+ var endState = !this.checked;
+ if ( is_opera ) { // opera has already toggled the checkbox by this point
+ endState = !endState;
+ }
+ var start, finish;
+ if ( this.index < lastCheckbox ) {
+ start = this.index + 1;
+ finish = lastCheckbox;
+ } else {
+ start = lastCheckbox;
+ finish = this.index - 1;
+ }
+ for (var i = start; i <= finish; ++i ) {
+ checkboxes[i].checked = endState;
+ }
+ lastCheckbox = this.index;
+ return true;
+}
+
+function toggle_element_activation(ida,idb) {
+ if (!document.getElementById) {
+ return;
+ }
+ document.getElementById(ida).disabled=true;
+ document.getElementById(idb).disabled=false;
+}
+
+function toggle_element_check(ida,idb) {
+ if (!document.getElementById) {
+ return;
+ }
+ document.getElementById(ida).checked=true;
+ document.getElementById(idb).checked=false;
+}
+
+function fillDestFilename(id) {
+ if (!document.getElementById) {
+ return;
+ }
+ var path = document.getElementById(id).value;
+ // Find trailing part
+ var slash = path.lastIndexOf('/');
+ var backslash = path.lastIndexOf('\\');
+ var fname;
+ if (slash == -1 && backslash == -1) {
+ fname = path;
+ } else if (slash > backslash) {
+ fname = path.substring(slash+1, 10000);
+ } else {
+ fname = path.substring(backslash+1, 10000);
+ }
+
+ // Capitalise first letter and replace spaces by underscores
+ fname = fname.charAt(0).toUpperCase().concat(fname.substring(1,10000)).replace(/ /g, '_');
+
+ // Output result
+ var destFile = document.getElementById('wpDestFile');
+ if (destFile) {
+ destFile.value = fname;
+ }
+}
+
+function scrollEditBox() {
+ var editBoxEl = document.getElementById("wpTextbox1");
+ var scrollTopEl = document.getElementById("wpScrolltop");
+ var editFormEl = document.getElementById("editform");
+
+ if (editBoxEl && scrollTopEl) {
+ if (scrollTopEl.value) { editBoxEl.scrollTop = scrollTopEl.value; }
+ editFormEl.onsubmit = function() {
+ document.getElementById("wpScrolltop").value = document.getElementById("wpTextbox1").scrollTop;
+ };
+ }
+}
+
+hookEvent("load", scrollEditBox);
+
+var allmessages_nodelist = false;
+var allmessages_modified = false;
+var allmessages_timeout = false;
+var allmessages_running = false;
+
+function allmessagesmodified() {
+ allmessages_modified = !allmessages_modified;
+ allmessagesfilter();
+}
+
+function allmessagesfilter() {
+ if ( allmessages_timeout )
+ window.clearTimeout( allmessages_timeout );
+
+ if ( !allmessages_running )
+ allmessages_timeout = window.setTimeout( 'allmessagesfilter_do();', 500 );
+}
+
+function allmessagesfilter_do() {
+ if ( !allmessages_nodelist )
+ return;
+
+ var text = document.getElementById('allmessagesinput').value;
+ var nodef = allmessages_modified;
+
+ allmessages_running = true;
+
+ for ( var name in allmessages_nodelist ) {
+ var nodes = allmessages_nodelist[name];
+ var display = ( name.indexOf( text ) == -1 ? 'none' : '' );
+
+ for ( var i = 0; i < nodes.length; i++)
+ nodes[i].style.display =
+ ( nodes[i].className == "def" && nodef
+ ? 'none' : display );
+ }
+
+ if ( text != document.getElementById('allmessagesinput').value ||
+ nodef != allmessages_modified )
+ allmessagesfilter_do(); // repeat
+
+ allmessages_running = false;
+}
+
+function allmessagesfilter_init() {
+ if ( allmessages_nodelist )
+ return;
+
+ var nodelist = new Array();
+ var templist = new Array();
+
+ var table = document.getElementById('allmessagestable');
+ if ( !table ) return;
+
+ var rows = document.getElementsByTagName('tr');
+ for ( var i = 0; i < rows.length; i++ ) {
+ var id = rows[i].getAttribute('id')
+ if ( id && id.substring(0,16) != 'sp-allmessages-r' ) continue;
+ templist[ id ] = rows[i];
+ }
+
+ var spans = table.getElementsByTagName('span');
+ for ( var i = 0; i < spans.length; i++ ) {
+ var id = spans[i].getAttribute('id')
+ if ( id && id.substring(0,17) != 'sp-allmessages-i-' ) continue;
+ if ( !spans[i].firstChild || spans[i].firstChild.nodeType != 3 ) continue;
+
+ var nodes = new Array();
+ var row1 = templist[ id.replace('i', 'r1') ];
+ var row2 = templist[ id.replace('i', 'r2') ];
+
+ if ( row1 ) nodes[nodes.length] = row1;
+ if ( row2 ) nodes[nodes.length] = row2;
+ nodelist[ spans[i].firstChild.nodeValue ] = nodes;
+ }
+
+ var k = document.getElementById('allmessagesfilter');
+ if (k) { k.style.display = ''; }
+
+ allmessages_nodelist = nodelist;
+}
+
+hookEvent( "load", allmessagesfilter_init );
+
+/*
+ Written by Jonathan Snook, http://www.snook.ca/jonathan
+ Add-ons by Robert Nyman, http://www.robertnyman.com
+ Author says "The credit comment is all it takes, no license. Go crazy with it!:-)"
+ From http://www.robertnyman.com/2005/11/07/the-ultimate-getelementsbyclassname/
+*/
+function getElementsByClassName(oElm, strTagName, oClassNames){
+ var arrElements = (strTagName == "*" && oElm.all)? oElm.all : oElm.getElementsByTagName(strTagName);
+ var arrReturnElements = new Array();
+ var arrRegExpClassNames = new Array();
+ if(typeof oClassNames == "object"){
+ for(var i=0; i<oClassNames.length; i++){
+ arrRegExpClassNames.push(new RegExp("(^|\\s)" + oClassNames[i].replace(/\-/g, "\\-") + "(\\s|$)"));
+ }
+ }
+ else{
+ arrRegExpClassNames.push(new RegExp("(^|\\s)" + oClassNames.replace(/\-/g, "\\-") + "(\\s|$)"));
+ }
+ var oElement;
+ var bMatchesAll;
+ for(var j=0; j<arrElements.length; j++){
+ oElement = arrElements[j];
+ bMatchesAll = true;
+ for(var k=0; k<arrRegExpClassNames.length; k++){
+ if(!arrRegExpClassNames[k].test(oElement.className)){
+ bMatchesAll = false;
+ break;
+ }
+ }
+ if(bMatchesAll){
+ arrReturnElements.push(oElement);
+ }
+ }
+ return (arrReturnElements)
+}
+
+function redirectToFragment(fragment) {
+ var match = navigator.userAgent.match(/AppleWebKit\/(\d+)/);
+ if (match) {
+ var webKitVersion = parseInt(match[1]);
+ if (webKitVersion < 420) {
+ // Released Safari w/ WebKit 418.9.1 messes up horribly
+ // Nightlies of 420+ are ok
+ return;
+ }
+ }
+ if (is_gecko) {
+ // Mozilla needs to wait until after load, otherwise the window doesn't scroll
+ addOnloadHook(function () {
+ if (window.location.hash == "")
+ window.location.hash = fragment;
+ });
+ } else {
+ if (window.location.hash == "")
+ window.location.hash = fragment;
+ }
+}
+
+/*
+ * Table sorting script by Joost de Valk, check it out at http://www.joostdevalk.nl/code/sortable-table/.
+ * Based on a script from http://www.kryogenix.org/code/browser/sorttable/.
+ * Distributed under the MIT license: http://www.kryogenix.org/code/browser/licence.html .
+ *
+ * Copyright (c) 1997-2006 Stuart Langridge, Joost de Valk.
+ *
+ * @todo don't break on colspans/rowspans (bug 8028)
+ * @todo language-specific digit grouping/decimals (bug 8063)
+ * @todo support all accepted date formats (bug 8226)
+ */
+
+var ts_image_path = stylepath+"/common/images/";
+var ts_image_up = "sort_up.gif";
+var ts_image_down = "sort_down.gif";
+var ts_image_none = "sort_none.gif";
+var ts_europeandate = wgContentLanguage != "en"; // The non-American-inclined can change to "true"
+var ts_alternate_row_colors = true;
+var SORT_COLUMN_INDEX;
+
+function sortables_init() {
+ var idnum = 0;
+ // Find all tables with class sortable and make them sortable
+ var tables = getElementsByClassName(document, "table", "sortable");
+ for (var ti = 0; ti < tables.length ; ti++) {
+ if (!tables[ti].id) {
+ tables[ti].setAttribute('id','sortable_table_id_'+idnum);
+ ++idnum;
+ }
+ ts_makeSortable(tables[ti]);
+ }
+}
+
+function ts_makeSortable(table) {
+ var firstRow;
+ if (table.rows && table.rows.length > 0) {
+ if (table.tHead && table.tHead.rows.length > 0) {
+ firstRow = table.tHead.rows[table.tHead.rows.length-1];
+ } else {
+ firstRow = table.rows[0];
+ }
+ }
+ if (!firstRow) return;
+
+ // We have a first row: assume it's the header, and make its contents clickable links
+ for (var i = 0; i < firstRow.cells.length; i++) {
+ var cell = firstRow.cells[i];
+ if ((" "+cell.className+" ").indexOf(" unsortable ") == -1) {
+ cell.innerHTML += '&nbsp;&nbsp;<a href="#" class="sortheader" onclick="ts_resortTable(this);return false;"><span class="sortarrow"><img src="'+ ts_image_path + ts_image_none + '" alt="&darr;"/></span></a>';
+ }
+ }
+ if (ts_alternate_row_colors) {
+ ts_alternate(table);
+ }
+}
+
+function ts_getInnerText(el) {
+ if (typeof el == "string") return el;
+ if (typeof el == "undefined") { return el };
+ if (el.innerText) return el.innerText; // Not needed but it is faster
+ var str = "";
+
+ var cs = el.childNodes;
+ var l = cs.length;
+ for (var i = 0; i < l; i++) {
+ switch (cs[i].nodeType) {
+ case 1: //ELEMENT_NODE
+ str += ts_getInnerText(cs[i]);
+ break;
+ case 3: //TEXT_NODE
+ str += cs[i].nodeValue;
+ break;
+ }
+ }
+ return str;
+}
+
+function ts_resortTable(lnk) {
+ // get the span
+ var span = lnk.getElementsByTagName('span')[0];
+
+ var td = lnk.parentNode;
+ var tr = td.parentNode;
+ var column = td.cellIndex;
+
+ var table = tr.parentNode;
+ while (table && !(table.tagName && table.tagName.toLowerCase() == 'table'))
+ table = table.parentNode;
+ if (!table) return;
+
+ // Work out a type for the column
+ if (table.rows.length <= 1) return;
+
+ // Skip the first row if that's where the headings are
+ var rowStart = (table.tHead && table.tHead.rows.length > 0 ? 0 : 1);
+
+ var itm = "";
+ for (var i = rowStart; i < table.rows.length; i++) {
+ if (table.rows[i].cells.length > column) {
+ itm = ts_getInnerText(table.rows[i].cells[column]);
+ itm = itm.replace(/^[\s\xa0]+/, "").replace(/[\s\xa0]+$/, "");
+ if (itm != "") break;
+ }
+ }
+
+ sortfn = ts_sort_caseinsensitive;
+ if (itm.match(/^\d\d[\/. -][a-zA-Z]{3}[\/. -]\d\d\d\d$/))
+ sortfn = ts_sort_date;
+ if (itm.match(/^\d\d[\/.-]\d\d[\/.-]\d\d\d\d$/))
+ sortfn = ts_sort_date;
+ if (itm.match(/^\d\d[\/.-]\d\d[\/.-]\d\d$/))
+ sortfn = ts_sort_date;
+ if (itm.match(/^[\u00a3$\u20ac]/)) // pound dollar euro
+ sortfn = ts_sort_currency;
+ if (itm.match(/^[\d.,]+\%?$/))
+ sortfn = ts_sort_numeric;
+
+ var reverse = (span.getAttribute("sortdir") == 'down');
+
+ var newRows = new Array();
+ for (var j = rowStart; j < table.rows.length; j++) {
+ var row = table.rows[j];
+ var keyText = ts_getInnerText(row.cells[column]);
+ var oldIndex = (reverse ? -j : j);
+
+ newRows[newRows.length] = new Array(row, keyText, oldIndex);
+ }
+
+ newRows.sort(sortfn);
+
+ var arrowHTML;
+ if (reverse) {
+ arrowHTML = '<img src="'+ ts_image_path + ts_image_down + '" alt="&darr;"/>';
+ newRows.reverse();
+ span.setAttribute('sortdir','up');
+ } else {
+ arrowHTML = '<img src="'+ ts_image_path + ts_image_up + '" alt="&uarr;"/>';
+ span.setAttribute('sortdir','down');
+ }
+
+ // We appendChild rows that already exist to the tbody, so it moves them rather than creating new ones
+ // don't do sortbottom rows
+ for (var i = 0; i < newRows.length; i++) {
+ if ((" "+newRows[i][0].className+" ").indexOf(" sortbottom ") == -1)
+ table.tBodies[0].appendChild(newRows[i][0]);
+ }
+ // do sortbottom rows only
+ for (var i = 0; i < newRows.length; i++) {
+ if ((" "+newRows[i][0].className+" ").indexOf(" sortbottom ") != -1)
+ table.tBodies[0].appendChild(newRows[i][0]);
+ }
+
+ // Delete any other arrows there may be showing
+ var spans = getElementsByClassName(tr, "span", "sortarrow");
+ for (var i = 0; i < spans.length; i++) {
+ spans[i].innerHTML = '<img src="'+ ts_image_path + ts_image_none + '" alt="&darr;"/>';
+ }
+ span.innerHTML = arrowHTML;
+
+ ts_alternate(table);
+}
+
+function ts_dateToSortKey(date) {
+ // y2k notes: two digit years less than 50 are treated as 20XX, greater than 50 are treated as 19XX
+ if (date.length == 11) {
+ switch (date.substr(3,3).toLowerCase()) {
+ case "jan": var month = "01"; break;
+ case "feb": var month = "02"; break;
+ case "mar": var month = "03"; break;
+ case "apr": var month = "04"; break;
+ case "may": var month = "05"; break;
+ case "jun": var month = "06"; break;
+ case "jul": var month = "07"; break;
+ case "aug": var month = "08"; break;
+ case "sep": var month = "09"; break;
+ case "oct": var month = "10"; break;
+ case "nov": var month = "11"; break;
+ case "dec": var month = "12"; break;
+ // default: var month = "00";
+ }
+ return date.substr(7,4)+month+date.substr(0,2);
+ } else if (date.length == 10) {
+ if (ts_europeandate == false) {
+ return date.substr(6,4)+date.substr(0,2)+date.substr(3,2);
+ } else {
+ return date.substr(6,4)+date.substr(3,2)+date.substr(0,2);
+ }
+ } else if (date.length == 8) {
+ yr = date.substr(6,2);
+ if (parseInt(yr) < 50) {
+ yr = '20'+yr;
+ } else {
+ yr = '19'+yr;
+ }
+ if (ts_europeandate == true) {
+ return yr+date.substr(3,2)+date.substr(0,2);
+ } else {
+ return yr+date.substr(0,2)+date.substr(3,2);
+ }
+ }
+ return "00000000";
+}
+
+function ts_parseFloat(num) {
+ if (!num) return 0;
+ num = parseFloat(num.replace(/,/, ""));
+ return (isNaN(num) ? 0 : num);
+}
+
+function ts_sort_date(a,b) {
+ var aa = ts_dateToSortKey(a[1]);
+ var bb = ts_dateToSortKey(b[1]);
+ return (aa < bb ? -1 : aa > bb ? 1 : a[2] - b[2]);
+}
+
+function ts_sort_currency(a,b) {
+ var aa = ts_parseFloat(a[1].replace(/[^0-9.]/g,''));
+ var bb = ts_parseFloat(b[1].replace(/[^0-9.]/g,''));
+ return (aa != bb ? aa - bb : a[2] - b[2]);
+}
+
+function ts_sort_numeric(a,b) {
+ var aa = ts_parseFloat(a[1]);
+ var bb = ts_parseFloat(b[1]);
+ return (aa != bb ? aa - bb : a[2] - b[2]);
+}
+
+function ts_sort_caseinsensitive(a,b) {
+ var aa = a[1].toLowerCase();
+ var bb = b[1].toLowerCase();
+ return (aa < bb ? -1 : aa > bb ? 1 : a[2] - b[2]);
+}
+
+function ts_sort_default(a,b) {
+ return (a[1] < b[1] ? -1 : a[1] > b[1] ? 1 : a[2] - b[2]);
+}
+
+function ts_alternate(table) {
+ // Take object table and get all it's tbodies.
+ var tableBodies = table.getElementsByTagName("tbody");
+ // Loop through these tbodies
+ for (var i = 0; i < tableBodies.length; i++) {
+ // Take the tbody, and get all it's rows
+ var tableRows = tableBodies[i].getElementsByTagName("tr");
+ // Loop through these rows
+ // Start at 1 because we want to leave the heading row untouched
+ for (var j = 0; j < tableRows.length; j++) {
+ // Check if j is even, and apply classes for both possible results
+ var oldClasses = tableRows[j].className.split(" ");
+ var newClassName = "";
+ for (var k = 0; k < oldClasses.length; k++) {
+ if (oldClasses[k] != "" && oldClasses[k] != "even" && oldClasses[k] != "odd")
+ newClassName += oldClasses[k] + " ";
+ }
+ tableRows[j].className = newClassName + (j % 2 == 0 ? "even" : "odd");
+ }
+ }
+}
+
+/*
+ * End of table sorting code
+ */
+
+function runOnloadHook() {
+ // don't run anything below this for non-dom browsers
+ if (doneOnloadHook || !(document.getElementById && document.getElementsByTagName)) {
+ return;
+ }
+
+ // set this before running any hooks, since any errors below
+ // might cause the function to terminate prematurely
+ doneOnloadHook = true;
+
+ histrowinit();
+ unhidetzbutton();
+ tabbedprefs();
+ updateTooltipAccessKeys( null );
+ akeytt( null );
+ scrollEditBox();
+ setupCheckboxShiftClick();
+ sortables_init();
+
+ // Run any added-on functions
+ for (var i = 0; i < onloadFuncts.length; i++) {
+ onloadFuncts[i]();
+ }
+}
+
+//note: all skins should call runOnloadHook() at the end of html output,
+// so the below should be redundant. It's there just in case.
+hookEvent("load", runOnloadHook);
+
+hookEvent("load", mwSetupToolbar);
diff --git a/test-perl.pl b/test-perl.pl
new file mode 100644
index 0000000..4f2ea3d
--- /dev/null
+++ b/test-perl.pl
@@ -0,0 +1,67 @@
+#!/usr/bin/perl -Wall
+
+use strict;
+use warnings;
+use Data::YAML::Reader;
+
+my %test = (
+ name => "Unprintables",
+ in => [
+ "---",
+ "- \"\\z\\x01\\x02\\x03\\x04\\x05\\x06\\a\\x08\\t\\n\\v\\f\\r\\x0e\\x0f\"",
+ "- \"\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\e\\x1c\\x1d\\x1e\\x1f\"",
+ "- \" !\\\"#\$%&'()*+,-./\"",
+ "- 0123456789:;<=>?",
+ "- '\@ABCDEFGHIJKLMNO'",
+ "- 'PQRSTUVWXYZ[\\]^_'",
+ "- '`abcdefghijklmno'",
+ "- 'pqrstuvwxyz{|}~\177'",
+ "- \200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217",
+ "- \220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237",
+ "- \240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257",
+ "- \260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277",
+ "- \300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317",
+ "- \320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337",
+ "- \340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357",
+ "- \360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377",
+ "..."
+ ],
+ out => [
+ "\0\1\2\3\4\5\6\a\b\t\n\13\f\r\16\17",
+ "\20\21\22\23\24\25\26\27\30\31\32\e\34\35\36\37",
+ " !\"#\$%&'()*+,-./",
+ "0123456789:;<=>?",
+ "\@ABCDEFGHIJKLMNO",
+ "PQRSTUVWXYZ[\\]^_",
+ "`abcdefghijklmno",
+ "pqrstuvwxyz{|}~\177",
+ "\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217",
+ "\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237",
+ "\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257",
+ "\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277",
+ "\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317",
+ "\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337",
+ "\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357",
+ "\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377"
+ ],
+ );
+
+sub iter {
+ my $ar = shift;
+ return sub {
+ return shift @$ar;
+ };
+}
+
+my $yaml = Data::YAML::Reader->new;
+my $source = join( "\n", @{ $test{in} } ) . "\n";
+
+my $iter = iter( $test{in} );
+my $got = $yaml->read($iter) ;
+
+use Test::More tests => 1;
+unless ( is_deeply $got, $test{out}, "Result matches" ) {
+ local $Data::Dumper::Useqq = $Data::Dumper::Useqq = 1;
+ diag( Data::Dumper->Dump( [$got], ['$got'] ) );
+ diag( Data::Dumper->Dump( [$test{out}], ['$expected'] ) );
+ } \ No newline at end of file
diff --git a/test/__init__.py b/test/__init__.py
index 9f3cdc6..1f74147 100644
--- a/test/__init__.py
+++ b/test/__init__.py
@@ -1,20 +1,61 @@
-def TODO(func):
- """unittest test method decorator that ignores
- exceptions raised by test
-
- Used to annotate test methods for code that may
- not be written yet. Ignores failures in the
- annotated test method; fails if the text
- unexpectedly succeeds.
- """
- def wrapper(*args, **kw):
- try:
- func(*args, **kw)
- succeeded = True
- except:
- succeeded = False
- assert succeeded is False, \
- "%s marked TODO but passed" % func.__name__
- wrapper.__name__ = func.__name__
- wrapper.__doc__ = func.__doc__
- return wrapper
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import, print_function, unicode_literals
+import logging
+from test import test_reader, test_input
+import yamlish
+import unittest
+import yaml
+logging.basicConfig(level=logging.DEBUG)
+
+def generate_test_name(source):
+ out = source.replace(' ', '_').replace(':', '').lower()
+ return "test_%s" % out
+
+def create_test(test_src, tested_function):
+ def do_test_expected(self):
+ #self.assertEqual(under_test(pair[0]), pair[1])
+ if ('skip' in test_src) and test_src['skip']:
+ logging.info("test_src skipped!")
+ return
+
+ # rather keep original tests in lists even though we could
+ # do multiline strings
+ source = "\n".join(test_src['in']) + "\n"
+ logging.debug("source = %s", source)
+
+ got = ""
+ if 'error' in test_src:
+ self.assertRaises(test_src['error'], tested_function, test_src['in'])
+ else:
+ want = test_src['out']
+ got = tested_function(test_src['in'])
+ logging.debug("test_src['out'] = %s", unicode(test_src['out']))
+ self.assertEqual(got, want, """Result matches
+ expected = %s
+
+ observed = %s
+ """ % (want, got))
+
+ return do_test_expected
+
+
+def generate_testsuite(test_data, test_case_shell, test_fce):
+ for in_test in test_data:
+ if ('skip' in in_test) and in_test['skip']:
+ logging.info("test %s skipped!", in_test['name'])
+ continue
+ name = generate_test_name(in_test['name'])
+ test_method = create_test (in_test, test_fce)
+ test_method.__name__ = str('test_%s' % name)
+ setattr (test_case_shell, test_method.__name__, test_method)
+
+class TestInput(unittest.TestCase):
+ pass
+
+class TestReader(unittest.TestCase):
+ pass
+
+if __name__ == "__main__":
+ generate_testsuite(test_reader.test_data_list, TestReader, yamlish.load)
+ generate_testsuite(test_input.test_data_list, TestInput, yamlish.load)
+ unittest.main()
diff --git a/test/all_tests.py b/test/all_tests.py
index 4a1a532..66e069b 100644
--- a/test/all_tests.py
+++ b/test/all_tests.py
@@ -1,16 +1,22 @@
+import sys
+import os.path
+sys.path.insert(0, os.path.realpath(os.path.dirname(__file__) + "/.."))
+
+import logging
+logging.basicConfig(level=logging.INFO)
import unittest
import test_load
import test_input
-#import test_reader
+import test_reader
import test_output
-#import test_writer
+import test_writer
if __name__ == "__main__":
loader = unittest.TestLoader()
suite = loader.loadTestsFromModule(test_load)
- suite.addTests(loader.loadTestsFromModule(test_input))
- #suite.addTests(loader.loadTestsFromModule(test_reader))
- suite.addTests(loader.loadTestsFromModule(test_output))
+ #suite.addTests(loader.loadTestsFromModule(test_input))
+ suite.addTests(loader.loadTestsFromModule(test_reader))
+ #suite.addTests(loader.loadTestsFromModule(test_output))
#suite.addTests(loader.loadTestsFromModule(test_writer))
runner = unittest.TextTestRunner(verbosity=2)
diff --git a/test/test_input.py b/test/test_input.py
index d221830..d950f86 100644
--- a/test/test_input.py
+++ b/test/test_input.py
@@ -1,105 +1,66 @@
# -*- coding: utf-8 -*-
from __future__ import absolute_import, print_function, unicode_literals
-import logging
-import unittest
-import yamlish
-logging.basicConfig(format='%(levelname)s:%(funcName)s:%(message)s',
- level=logging.INFO)
-
-IN = """
- ---
- bill-to:
- address:
- city: "Royal Oak"
- lines: "458 Walkman Dr.\nSuite #292\n"
- postal: 48046
- state: MI
- family: Dumars
- given: Chris
- comments: "Late afternoon is best. Backup contact is Nancy Billsmer @ 338-4338\n"
- date: 2001-01-23
- invoice: 34843
- product:
- -
- description: Basketball
- price: 450.00
- quantity: 4
- sku: BL394D
- -
- description: "Super Hoop"
- price: 2392.00
- quantity: 1
- sku: BL4438H
- tax: 251.42
- total: 4443.52
- ...
-"""
-
-OUT = {
- 'bill-to': {
- 'given': 'Chris',
- 'address': {
- 'city': 'Royal Oak',
- 'postal': '48046',
- 'lines': "458 Walkman Dr.\nSuite #292\n",
- 'state': 'MI'
- },
- 'family': 'Dumars'
- },
- 'invoice': '34843',
- 'date': '2001-01-23',
- 'tax': '251.42',
- 'product': [
+test_data_list = [
{
- 'sku': 'BL394D',
- 'quantity': '4',
- 'price': '450.00',
- 'description': 'Basketball'
- },
- {
- 'sku': 'BL4438H',
- 'quantity': '1',
- 'price': '2392.00',
- 'description': 'Super Hoop'
- }
- ],
- 'comments':
- "Late afternoon is best. Backup contact is Nancy Billsmer @ 338-4338\n",
- 'total': '4443.52'
-}
-
-class TestInput(unittest.TestCase):
- """FIXME description of this class"""
- def test_reader(self):
- scalar = IN
- source = [
+ "name": "Input test",
+ "in": """---
+bill-to:
+ address:
+ city: "Royal Oak"
+ lines: "458 Walkman Dr.\\nSuite #292\\n"
+ postal: 48046
+ state: MI
+ family: Dumars
+ given: Chris
+comments: "Late afternoon is best. Backup contact is Nancy Billsmer @ 338-4338\\n"
+date: 2001-01-23
+invoice: 34843
+product:
+ -
+ description: Basketball
+ price: 450.00
+ quantity: 4
+ sku: BL394D
+ -
+ description: "Super Hoop"
+ price: 2392.00
+ quantity: 1
+ sku: BL4438H
+tax: 251.42
+total: 4443.52
+...
+""",
+ 'out': {
+ 'bill-to': {
+ 'given': 'Chris',
+ 'address': {
+ 'city': 'Royal Oak',
+ 'postal': 48046,
+ 'lines': "458 Walkman Dr.\nSuite #292\n",
+ 'state': 'MI'
+ },
+ 'family': 'Dumars'
+ },
+ 'invoice': 34843,
+ 'date': '2001-01-23',
+ 'tax': 251.42,
+ 'product': [
{
- "name": 'Array reference',
- "source": IN.split("\n"),
+ 'sku': 'BL394D',
+ 'quantity': 4,
+ 'price': 450.00,
+ 'description': 'Basketball'
},
-# {
-# "name": 'Closure',
-# "source": sub { shift @lines },
-# },
{
- "name": 'Scalar',
- "source": IN,
+ 'sku': 'BL4438H',
+ 'quantity': 1,
+ 'price': 2392.00,
+ 'description': 'Super Hoop'
}
- ]
-
- for src in source:
- name = src['name']
- yaml = yamlish.Reader()
- self.assert_(True, "%s: Created" % name)
- self.assert_(isinstance(yaml, yamlish.Reader))
-
- #my $got = eval { $yaml -> read($src -> {source}) };
- try:
- got = yaml.read(src['source'])
- except IOError: # FIXME not sure which one
- raise
- self.assertEqual(got, OUT, """%s: Result matches
- expected = %s
-
- observed = %s
- """ % (name, OUT, got))
+ ],
+ 'comments':
+ "Late afternoon is best. Backup contact is Nancy Billsmer @ 338-4338\n",
+ 'total': 4443.52
+ }
+ }
+]
diff --git a/test/test_load.py b/test/test_load.py
index 852dd29..a86364b 100644
--- a/test/test_load.py
+++ b/test/test_load.py
@@ -4,11 +4,9 @@ import unittest
class TestBasics(unittest.TestCase):
def test_import(self):
import yamlish
- from yamlish import Reader
- self.assert_(True, "Importing Reader.")
- from yamlish import Writer
- self.assert_(True, "Importing Writer.")
- self.assert_(True,
+ from yamlish import Reader #IGNORE:W0612
+ from yamlish import Writer #IGNORE:W0612
+ self.assertTrue(yamlish.__version__,
"Testing import of yamlish, version %s." % yamlish.__version__)
if __name__ == "__main__":
diff --git a/test/test_output.py b/test/test_output.py
index a8f5a43..ea8d841 100644
--- a/test/test_output.py
+++ b/test/test_output.py
@@ -3,7 +3,7 @@ from __future__ import absolute_import, print_function, unicode_literals
import re
import unittest
import yamlish
-from . import TODO
+import yaml
OUT = [
"---",
@@ -74,7 +74,7 @@ destination = [
{
"name": 'Array reference',
"destination": buf1,
- "normalise": (lambda x: buf1),
+ "normalise": (lambda : buf1),
},
# {
# "name": 'Closure',
@@ -89,15 +89,11 @@ destination = [
]
class TestOuptut(unittest.TestCase):
- @TODO
def test_output(self):
for dest in destination:
name = dest['name']
- yaml = yamlish.Writer()
- self.assert_(True, "%s: Created" % name)
- self.assert_(isinstance(yaml, yamlish.Writer))
- yaml.write(IN, dest[destination])
+ yaml.dump(IN, dest)
got = dest['normalise']()
self.assertEqual(got, OUT, """%s: Result matches
diff --git a/test/test_reader.py b/test/test_reader.py
index 1694abe..e8d39d1 100644
--- a/test/test_reader.py
+++ b/test/test_reader.py
@@ -1,10 +1,7 @@
# -*- coding: utf-8 -*-
-from __future__ import absolute_import, print_function, unicode_literals
-import re
-import unittest
-import yamlish
+import yaml
-SCHEDULE = [
+test_data_list = [
{
"name": 'Hello World',
"in": [ '--- Hello, World', '...', ],
@@ -26,45 +23,45 @@ SCHEDULE = [
"out": "Hello, World",
},
{
- "name": 'Hello World 4',
- "in": [ '--- >', ' Hello,', ' World', '...', ],
+ "name": 'Hello World 5',
+ "in": [ '--- >', ' Hello,', ' World', '...', ],
"out": "Hello, World\n",
},
{
- "name": 'Hello World 5',
- "in": [ '--- >', ' Hello,', ' World', '...', ],
- "error": re.compile(r"Missing\s+'[.][.][.]'"),
+ "name": 'Hello World 6',
+ "in": [ '--- >', ' Hello,', ' World', '...', ],
+ "error": yaml.parser.ParserError,
},
{
"name": 'Simple array',
"in": [ '---', '- 1', '- 2', '- 3', '...', ],
- "out": [ '1', '2', '3' ],
+ "out": [ 1, 2, 3 ],
},
{
"name": 'Mixed array',
- "in": [ '---', '- 1', '- \'two\'', '- "three\n"', '...', ],
- "out": [ '1', 'two', "three\n" ],
+ "in": [ '---', '- 1', "- 'two'", r'- "three\n"', '...', ],
+ "out": [ 1, 'two', "three\n" ],
},
{
"name": 'Hash in array',
- "in": [ '---', '- 1', '- two: 2', '- 3', '...', ],
- "out": [ '1', { "two": '2' }, '3' ],
+ "in": [ '---', ' - 1', ' - two: 2', ' - 3', '...', ],
+ "out": [ 1, { "two": 2 }, 3 ],
},
{
"name": 'Hash in array 2',
"in": [ '---', '- 1', '- two: 2', ' three: 3', '- 4', '...', ],
- "out": [ '1', { "two": '2', "three": '3' }, '4' ],
+ "out": [ 1, { "two": 2, "three": 3 }, 4 ],
},
{
"name": 'Nested array',
"in": [
'---',
'- one',
- '-',
- ' - two',
- ' -',
- ' - three',
- ' - four',
+ '- ',
+ ' - two',
+ ' - ',
+ ' - three',
+ ' - four',
'- five',
'...',
],
@@ -83,8 +80,8 @@ SCHEDULE = [
'...',
],
"out": {
- "one": { "two": { "three": '3', "four": '4' }, "five": '5' },
- "six": '6'
+ "one": { "two": { "three": 3, "four": 4 }, "five": 5 },
+ "six": 6
},
},
@@ -98,7 +95,7 @@ SCHEDULE = [
' given : Chris',
' family : Dumars',
' address:',
- ' lines: |',
+ ' lines: | ',
' 458 Walkman Dr.',
' Suite #292',
' city : Royal Oak',
@@ -122,36 +119,36 @@ SCHEDULE = [
'...',
],
"out": {
- "bill - to": {
+ "bill-to": {
"given": 'Chris',
"address": {
"city": 'Royal Oak',
- "postal": '48046',
+ "postal": 48046,
"lines": "458 Walkman Dr.\nSuite #292\n",
"state": 'MI'
},
"family": 'Dumars'
},
- "invoice": '34843',
+ "invoice": 34843,
"date": '2001-01-23',
- "tax": '251.42',
+ "tax": 251.42,
"product": [
{
"sku": 'BL394D',
- "quantity": '4',
- "price": '450.00',
+ "quantity": 4,
+ "price": 450.00,
"description": 'Basketball'
},
{
"sku": 'BL4438H',
- "quantity": '1',
- "price": '2392.00',
+ "quantity": 1,
+ "price": 2392.00,
"description": 'Super Hoop'
}
],
'comments':
"Late afternoon is best. Backup contact is Nancy Billsmer @ 338-4338\n",
- "total": '4443.52'
+ "total": 4443.52
}
},
@@ -159,24 +156,25 @@ SCHEDULE = [
{
"in": ['...'],
"name": 'Regression: empty',
- "error": re.compile(r"document\s+header\s+not\s+found")
+ "error": yaml.parser.ParserError,
},
{
"in": [ '# comment', '...' ],
"name": 'Regression: only_comment',
- "error": re.compile(r"document\s+ header\s+ not\s+ found")
+ "error": yaml.parser.ParserError,
},
{
+ "skip": True, # A corner case, which is apparently not
+ # clear even from the spec file
"out": None,
"in": [ '---', '...' ],
"name": 'Regression: only_header',
- "error": re.compile(r"Premature\s+end", re.I),
+ "x-error": yaml.parser.ParserError,
},
{
- "out": None,
"in": [ '---', '---', '...' ],
"name": 'Regression: two_header',
- "error": re.compile(r"Unexpected\s+start", re.I),
+ "error": yaml.composer.ComposerError,
},
{
"out": None,
@@ -191,7 +189,7 @@ SCHEDULE = [
{
"in": [ '--- ~', '---', '...' ],
"name": 'Regression: two_undef',
- "error": re.compile(r"Missing\s+'[.][.][.]'"),
+ "error": yaml.composer.ComposerError,
},
{
"out": 'foo',
@@ -206,7 +204,7 @@ SCHEDULE = [
{
"in": [ '--- foo', '--- bar', '...' ],
"name": 'Regression: two_scalar',
- "error": re.compile(r"Missing\s+'[.][.][.]'"),
+ "error": yaml.composer.ComposerError,
},
{
"out": ['foo'],
@@ -310,49 +308,49 @@ SCHEDULE = [
},
{
"name": "Unprintables",
+ "skip": False,
"in": [
- " - - -",
- " - \"\\z\\x01\\x02\\x03\\x04\\x05\\x06\\a\\x08\\t\\n\\v\\f\\r\\x0e\\x0f\"",
- "- \"\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\e\\x1c\\x1d\\x1e\\x1f\"",
- "- \" !\\\"#\$%&'()*+,-./\"",
- "- 0123456789:;<=>?",
- "- '\@ABCDEFGHIJKLMNO'",
- "- 'PQRSTUVWXYZ[\\]^_'",
- "- '`abcdefghijklmno'",
- "- 'pqrstuvwxyz{|}~\177'",
- "- \200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217",
- "- \220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237",
- "- \240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257",
- "- \260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277",
- "- \300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317",
- "- \320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337",
- "- \340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357",
- "- \360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377",
- "..."
- ],
+ "---",
+ "- \"\\z\\x01\\x02\\x03\\x04\\x05\\x06\\a\\x08\\t\\n\\v\\f\\r\\x0e\\x0f\"",
+ "- \"\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\e\\x1c\\x1d\\x1e\\x1f\"",
+ "- \" !\\\"#\$%&'()*+,-./\"",
+ "- 0123456789:;<=>?",
+ "- '\@ABCDEFGHIJKLMNO'",
+ "- 'PQRSTUVWXYZ[\\]^_'",
+ "- '`abcdefghijklmno'",
+ "- 'pqrstuvwxyz{|}~\177'",
+ "- \200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217",
+ "- \220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237",
+ "- \240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257",
+ "- \260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277",
+ "- \300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317",
+ "- \320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337",
+ "- \340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357",
+ "- \360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377",
+ "..."],
"out": [
- "\0\1\2\3\4\5\6\a\b\t\n\13\f\r\16\17",
- "\20\21\22\23\24\25\26\27\30\31\32\e\34\35\36\37",
- " !\"#\$%&'()*+,-./",
- "0123456789:;<=>?",
- "\@ABCDEFGHIJKLMNO",
- "PQRSTUVWXYZ[\\]^_",
- "`abcdefghijklmno",
- "pqrstuvwxyz{|}~\177",
- "\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217",
- "\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237",
- "\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257",
- "\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277",
- "\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317",
- "\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337",
- "\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357",
- "\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377"
- ],
+ "\0\1\2\3\4\5\6\a\b\t\n\13\f\r\16\17",
+ "\20\21\22\23\24\25\26\27\30\31\32\e\34\35\36\37",
+ " !\"#\$%&'()*+,-./",
+ "0123456789:;<=>?",
+ "\@ABCDEFGHIJKLMNO",
+ "PQRSTUVWXYZ[\\]^_",
+ "`abcdefghijklmno",
+ "pqrstuvwxyz{|}~\177",
+ "\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217",
+ "\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237",
+ "\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257",
+ "\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277",
+ "\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317",
+ "\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337",
+ "\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357",
+ "\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377"
+ ]
},
{
"name": 'Quoted hash keys',
"in": [
- '---', ' "quoted": Magic!', ' "\n\t": newline, tab', '...',
+ '---', ' "quoted": Magic!', ' "\\n\\t": newline, tab', '...',
],
"out": {
"quoted": 'Magic!',
@@ -360,63 +358,3 @@ SCHEDULE = [
},
},
]
-
-# FIXME plan(tests=(len(SCHEDULE) * 5))
-
-#sub iter {
-# my $ar = shift;
-# return sub {
-# return shift @$ar;
-# };
-#}
-
-class TestReader(unittest.TestCase):
- def test_reader(self):
- for test in SCHEDULE:
- name = test['name']
- yaml = yamlish.Reader()
- self.assert_(True, "%s: Created" % name)
- self.assert_(isinstance(yaml, yamlish.Reader))
-
- # diag "$name\n";
-
- # unless ( $test->{in} ) {
- # pass for 1 .. 2;
- # use YAML;
- # diag "Input for test:\n";
- # diag( Dump( $test->{out} ) );
- # next;
- # }
-
- source = "\n".join([line for line in test['in']]) + "\n"
-
- try:
- got = yaml.read(test['in']) # expecting test['in'] being an iterator
- except IOError as exc: # FIXME no idea what
- dollar_at = exc
-
- raw = yaml.get_raw()
-
- err = test['error'] # RE for testing results
- if err: # if we have err, use it
- if not err.search(dollar_at): # FIXME $@ (or dollar_at) is described
- # in perlvar(1) the error status of the last eval(), which
- # means that yaml.read(test['in'])
- # if everything is alright, then it is None
- self.assertFalse("%s: Error message" % name)
- raise Exception(dollar_at)
- self.assert_(not got, "%s: No result" % name)
- else:
- want = test['out']
- self.assert_(not dollar_at, "%s: No error\n%s" % (name, dollar_at))
-
- self.assertEqual(got, want, """%s: Result matches
- expected = %s
-
- observed = %s
- """ % (name, want, got))
- self.assertEqual(raw, source, """%s: Captured source matches
- expected = %s
-
- observed = %s
- """ % (name, raw, source))
diff --git a/test/test_writer.py b/test/test_writer.py
index 5b0a8c4..d4ee5ba 100644
--- a/test/test_writer.py
+++ b/test/test_writer.py
@@ -4,7 +4,7 @@ from __future__ import absolute_import, print_function, unicode_literals
import unittest
import yamlish
-SCHEDULE = [
+test_data_list = [
{
"name": 'Simple scalar',
"in": 1,
@@ -138,50 +138,30 @@ SCHEDULE = [
},
]
-# plan(tests = len(SCHEDULE) * 5)
+# plan(tests = len(test_data_list) * 5)
class TestWriter(unittest.TestCase):
def test_writer(self):
- for test in SCHEDULE:
+ for test in test_data_list:
name = test['name']
- yaml = yamlish.Writer()
- self.assert_(True, "%s: Created" % name)
- self.assert_(isinstance(yaml, yamlish.Writer))
-
- got = []
data = test['in']
- try:
- yaml.write(data, got)
- except Exception as exc:
- dollar_at = exc
- raise
-
- # FIXME just to say ... THERE IS NO 'error' key in SCHEDULE!!!
- err = test['error']
- if err:
- if not err.search(dollar_at): # FIXME $@ (or dollar_at) is described
- # in perlvar(1) the error status of the last eval(), which
- # means that yaml.read(test['in'])
- # if everything is alright, then it is None
- self.assertFalse("%s: Error message" % name)
- raise Exception(dollar_at)
- self.assert_(not got, "%s: No result" % name)
+ got = []
+ # We currently don't throw any exceptions in Writer, so this
+ # this is always false
+ if 'error' in test:
+ self.assertRaises(test['error'], yamlish.write, test['in'])
else:
want = test['out']
- self.assert_(not dollar_at, "%s: No error\n%s" % (name, dollar_at))
-
+ yamlish.write(test['in'], got)
self.assertEqual(got, want, """%s: Result matches
expected = %s
observed = %s
""" % (name, want, got))
- yr = yamlish.Reader()
-
# Now try parsing it
- parsed = yr.read(got) # FIXME got has an iterator
-
+ parsed = yamlish.load(got) # FIXME got has an iterator
self.assertEqual(parsed, data, """%s: Reparse OK
expected = %s
diff --git a/yamlish.py b/yamlish.py
index d26c8be..b3b41c5 100644
--- a/yamlish.py
+++ b/yamlish.py
@@ -1,87 +1,189 @@
# -*- coding: utf-8 -*-
+"""
+=head1 NAME
+
+Data::YAML - Easy YAML serialisation of Perl data structures
+
+=head1 VERSION
+
+This document describes Data::YAML version 0.0.6
+
+=head1 DESCRIPTION
+
+In the spirit of L<YAML::Tiny>, L<Data::YAML::Reader> and
+L<Data::YAML::Writer> provide lightweight, dependency-free YAML
+handling. While C<YAML::Tiny> is designed principally for working with
+configuration files C<Data::YAML> concentrates on the transparent round-
+tripping of YAML serialized Perl data structures.
+
+As an example of why this distinction matters consider that
+C<YAML::Tiny> doesn't handle hashes with keys containing non-printable
+characters. This is fine for configuration files but likely to cause
+problems when handling arbitrary Perl data structures. C<Data::YAML>
+handles exotic hash keys correctly.
+
+The syntax accepted by C<Data::YAML> is a subset of YAML. Specifically
+it is the same subset of YAML that L<Data::YAML::Writer> produces. See
+L<Data::YAML> for more information.
+
+=head2 YAML syntax
+
+Although YAML appears to be a simple language the entire YAML
+specification is huge. C<Data::YAML> implements a small subset of the
+complete syntax trading completeness for compactness and simplicity.
+This restricted syntax is known (to me at least) as 'YAMLish'.
+
+These examples demonstrates the full range of supported syntax.
+
+All YAML documents must begin with '---' and end with a line
+containing '...'.
+
+ --- Simple scalar
+ ...
+
+Unprintable characters are represented using standard escapes in double
+quoted strings.
+
+ --- "\t\x01\x02\n"
+ ...
+
+Array and hashes are represented thusly
+
+ ---
+ - "This"
+ - "is"
+ - "an"
+ - "array"
+ ...
+
+ ---
+ This: is
+ a: hash
+ ...
+
+Structures may nest arbitrarily
+
+ ---
+ -
+ name: 'Hash one'
+ value: 1
+ -
+ name: 'Hash two'
+ value: 2
+ ...
+
+Undef is a tilde
+
+ --- ~
+ ...
+=head2 Uses
+
+Use C<Data::YAML> may be used any time you need to freeze and thaw Perl
+data structures into a human readable format. The output from
+C<Data::YAML::Writer> should be readable by any YAML parser.
+
+C<Data::YAML> was originally written to allow machine-readable
+diagnostic information to be passed from test scripts to
+L<TAP::Harness>. That means that if you're writing a testing system that
+needs to output TAP version 13 or later syntax you might find
+C<Data::YAML> useful.
+
+Read more about TAP and YAMLish here: L<http://testanything.org/wiki>
+
+=head1 BUGS AND LIMITATIONS
+
+No bugs have been reported.
+
+Please report any bugs or feature requests to
+C<data-yaml@rt.cpan.org>, or through the web interface at
+L<http://rt.cpan.org>.
+
+=head1 AUTHOR
+
+Andy Armstrong C<< <andy@hexten.net> >>
+
+=head1 LICENCE AND COPYRIGHT
+
+Copyright (c) 2007, Andy Armstrong C<< <andy@hexten.net> >>. All rights reserved.
+
+This module is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself. See L<perlartistic>.
+
+=head1 DISCLAIMER OF WARRANTY
+
+BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
+EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH
+YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
+NECESSARY SERVICING, REPAIR, OR CORRECTION.
+
+IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE
+LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL,
+OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
+THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+"""
+
+import logging
import yaml
-import pprint
__version__ = "0.1"
-IN = """
----
-bill-to:
- address:
- city: "Royal Oak"
- lines: "458 Walkman Dr.\nSuite #292\n"
- postal: 48046
- state: MI
- family: Dumars
- given: Chris
-comments: "Late afternoon is best. Backup contact is Nancy Billsmer @ 338-4338\n"
-date: 2001-01-23
-invoice: 34843
-product:
- -
- description: Basketball
- price: 450.00
- quantity: 4
- sku: BL394D
- -
- description: "Super Hoop"
- price: 2392.00
- quantity: 1
- sku: BL4438H
-tax: 251.42
-total: 4443.52
-...
-"""
+class YamlishLoader(yaml.reader.Reader, yaml.scanner.Scanner,
+ yaml.parser.Parser, yaml.composer.Composer,
+ yaml.constructor.SafeConstructor, yaml.resolver.Resolver):
+ def __init__(self, stream):
+ yaml.reader.Reader.__init__(self, stream)
+ yaml.scanner.Scanner.__init__(self)
+ yaml.parser.Parser.__init__(self)
+ yaml.composer.Composer.__init__(self)
+ yaml.constructor.SafeConstructor.__init__(self)
+ yaml.resolver.Resolver.__init__(self)
+
+ @classmethod
+ def remove_implicit_resolver(cls, tag):
+ if not 'yaml_implicit_resolvers' in cls.__dict__:
+ cls.yaml_implicit_resolvers = cls.yaml_implicit_resolvers.copy()
+ for key in cls.yaml_implicit_resolvers:
+ resolvers_set = cls.yaml_implicit_resolvers[key]
+ for idx in range(len(resolvers_set)):
+ if resolvers_set[idx][0] == tag:
+ del resolvers_set[idx]
+ if len(resolvers_set) == 0:
+ del cls.yaml_implicit_resolvers[key]
+
+YamlishLoader.remove_implicit_resolver(u'tag:yaml.org,2002:timestamp')
+
+def load(source):
+ out = None
+ logging.debug("instr:\n%s", source)
+ if isinstance(source, (str, unicode)):
+ out = yaml.load(source, Loader=YamlishLoader)
+ logging.debug("out (string) = %s", out)
+ elif hasattr(source, "__iter__"):
+ instr = "\n".join(source)
+ out = yaml.load(instr, Loader=YamlishLoader)
+ logging.debug("out (iter) = %s", out)
+ return out
+
+def dump(source, destination):
+ if isinstance(destination, (str, unicode)):
+ with open(destination, "w") as outf:
+ dump(source, outf)
+ elif isinstance(destination, file):
+ yaml.dump(source, destination, canonical=False,
+ default_flow_style=False, default_style=False)
-OUT = {
- 'bill-to': {
- 'given': 'Chris',
- 'address': {
- 'city': 'Royal Oak',
- 'postal': '48046',
- 'lines': "458 Walkman Dr.\nSuite #292\n",
- 'state': 'MI'
- },
- 'family': 'Dumars'
- },
- 'invoice': '34843',
- 'date': '2001-01-23',
- 'tax': '251.42',
- 'product': [
- {
- 'sku': 'BL394D',
- 'quantity': '4',
- 'price': '450.00',
- 'description': 'Basketball'
- },
- {
- 'sku': 'BL4438H',
- 'quantity': '1',
- 'price': '2392.00',
- 'description': 'Super Hoop'
- }
- ],
- 'comments':
- "Late afternoon is best. Backup contact is Nancy Billsmer @ 338-4338\n",
- 'total': '4443.52'
-}
-
-class Reader(object):
- def __init__(self):
- pass
-
- def get_raw(self):
- pass
-
- def read(self, source):
- pass
-
-class Writer(object):
- def __init__(self):
- pass
-
- def write(self, source, destination):
- pass
-
-#print yaml.dump(OUT, canonical=False, default_flow_style=False, default_style=False)
+def dumps(source):
+ return yaml.dump(source, canonical=False,
+ default_flow_style=False, default_style=False)