test_system.html 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623
  1. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
  2. "http://www.w3.org/TR/html4/strict.dtd">
  3. <html>
  4. <head>
  5. <meta name="generator" content=
  6. "HTML Tidy for Linux/x86 (vers 1st March 2002), see www.w3.org">
  7. <!--tidy options: -i -wrap 78 -->
  8. <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
  9. <title>A testing system for B2</title>
  10. <style type="text/css">
  11. hr { color: black }
  12. p.revision { text-align: right; font-style: italic }
  13. pre.code { margin-left: 2em }
  14. pre.example { margin-left: 2em; border: solid black thin }
  15. pre.output { margin-left: 2em }
  16. img.banner { border: 0; float: left }
  17. h1 { text-align: right }
  18. br.clear { clear: left }
  19. div.attention { color: red }
  20. </style>
  21. </head>
  22. <body>
  23. <p><a href="../../../../index.htm"><img class="banner" height="86" width=
  24. "277" alt="C++ Boost" src="../../../../boost.png"></a></p>
  25. <h1>A testing system for B2<br class="clear">
  26. </h1>
  27. <hr>
  28. <dl class="page-index">
  29. <dt><a href="#sec-intro">Introduction for users</a></dt>
  30. <dd>
  31. <dl class="page-index">
  32. <dt><a href="#sec-command-line-options">Command line options</a></dt>
  33. </dl>
  34. </dd>
  35. <dt><a href="#sec-developers">Introduction for developers</a></dt>
  36. <dd>
  37. <dl class="page-index">
  38. <dt><a href="#sec-intro-changing">Changing the working
  39. directory</a></dt>
  40. <dt><a href="#sec-intro-examining">Examining the working directory and
  41. changing it</a></dt>
  42. <dt><a href="#sec-intro-results">Test result</a></dt>
  43. </dl>
  44. </dd>
  45. <dt><a href="#sec-reference">Reference documentation</a></dt>
  46. <dd>
  47. <dl class="page-index">
  48. <dt><a href="#method-__init__">Method __init__</a></dt>
  49. <dt><a href="#method-set_tree">Method <tt>set_tree</tt></a></dt>
  50. <dt><a href="#method-write">Method <tt>write</tt></a></dt>
  51. <dt><a href="#method-copy">Method <tt>copy</tt></a></dt>
  52. <dt><a href="#method-touch">Method <tt>touch</tt></a></dt>
  53. <dt><a href="#method-run_build_system">Method
  54. <tt>run_build_system</tt></a></dt>
  55. <dt><a href="#method-read">Method <tt>read</tt></a></dt>
  56. <dt><a href="#method-read_and_strip">Method
  57. <tt>read_and_strip</tt></a></dt>
  58. <dt><a href="#methods-expectations">Methods for declaring
  59. expectations</a></dt>
  60. <dt><a href="#methods-ignoring">Methods for ignoring
  61. changes</a></dt>
  62. <dt><a href="#methods-result">Methods for explicitly specifying
  63. results</a></dt>
  64. <dt><a href="#class-list">Helper class <tt>List</tt></a></dt>
  65. </dl>
  66. </dd>
  67. </dl>
  68. <hr>
  69. <h2><a name="sec-intro">Introduction for users</a></h2>
  70. <p>The testing system for B2 is a small set of Python modules and
  71. scripts for automatically testing user-obversable behaviour. It uses
  72. components from testing systems of <a href="http://www.scons.org">Scons</a>
  73. and <a href="http://subversion.tigris.org">Subversion</a>, together with
  74. some additional functionality.</p>
  75. <p>To run the tests you need to:</p>
  76. <ol>
  77. <li>Get the source tree of B2 (located at <tt>tools/build</tt>
  78. in Boost)</li>
  79. <li>Have <a href="http://www.python.org">Python</a> installed. Version
  80. 2.1 is known to work.</li>
  81. <li>Build Boost.Jam. See <a href=
  82. "../engine/index.html">$boost_build_root/engine/index.html</a> for
  83. instructions.</li>
  84. <li>Configure at least one toolset. You can edit <tt>site-config.jam</tt>
  85. or <tt>user-config.jam</tt> to add new toolsets. Or you can create file
  86. <tt>test-config.jam</tt> in <tt>$boost_build_root/test</tt> directory. In
  87. this case, <tt>site-config.jam</tt> and <tt>user-config.jam</tt> will be
  88. ignored for testing.</li>
  89. <li>Make sure that in the configuration jam file(s) that you use you generate
  90. no console output, ie. with the Boost Build 'ECHO' rule. Such console output
  91. in the configuration jam file(s) will cause a number of tests to automatically
  92. fail which would otherwise succeed.</li>
  93. </ol>
  94. <p>When all is set, you can run all the tests using the <tt>test_all.py</tt>
  95. script or you can run a specific test by starting its Python script
  96. directly.</p>
  97. <p>Examples:</p>
  98. <pre class="code">
  99. python test_all.py
  100. python generators_test.py
  101. </pre>
  102. <p>If everything is OK, you will see a list of passed tests. Otherwise, a
  103. failure will be reported.</p>
  104. <h3><a name="sec-command-line-options">Command line options</a></h3>
  105. <p>Test scripts will use the toolset you configured to be the default or
  106. you can specify a specific one on the command line:</p>
  107. <pre class="code">
  108. python test_all.py borland
  109. python generators_test.py msvc-7.1
  110. </pre>
  111. <p>Other test script flags you can specify on the command line are:</p>
  112. <ul>
  113. <li><tt>--default-bjam</tt> -- By default the test system will use the
  114. Boost Jam executable found built in its default development build
  115. location. This option makes it use the default one available on your
  116. system, i.e. the one found in the system path.</li>
  117. <li><tt>--preserve</tt> -- In case of a failed test its working
  118. directory will be copied to the "failed_test" directory under the
  119. current directory.</li>
  120. <li><tt>--verbose</tt> -- Makes the test system and the run build system
  121. display additional output. Note though that this may cause tests that
  122. check the build system output to fail.</li>
  123. </ul>
  124. <h2><a name="sec-developers">Introduction for developers</a></h2>
  125. <p>It is suggested that every new functionality come together with tests,
  126. and that bugfixes are accompanied by tests. There's no need to say that
  127. tests are good, but two points are extremely important:</p>
  128. <ul>
  129. <li>For an interpreted language like Jam, without any static checks,
  130. testing is simply the only sefeguard we can have.</li>
  131. <li>Good tests allow us to change internal design much more safely, and we
  132. have not gotten everything nailed down yet.</li>
  133. </ul>
  134. <p>Adding a new test is simple:</p>
  135. <ol>
  136. <li>Go to <tt>$boost_build_root/test/test_all.py</tt> and add new test
  137. name to the list at the end of the file. Suppose the test name is "hello".
  138. </li>
  139. <li>Add a new python module, in this example "hello.py", to do the actual
  140. testing.</li>
  141. </ol>
  142. <p>The module, in general will perform these basic actions:</p>
  143. <ol>
  144. <li>Set up the initial working directory state</li>
  145. <li>
  146. Run the build system and check the results:
  147. <ol>
  148. <li>generated output,</li>
  149. <li>changes made to the working directory,</li>
  150. <li>new content of the working directory.</li>
  151. </ol>
  152. </li>
  153. <li>Add, remove or touch files or change their content and then repeat
  154. the previous step until satisfied.</li>
  155. <li>Clean up</li>
  156. </ol>
  157. <p>The "hello.py" module might contain:</p>
  158. <pre class="example">
  159. from BoostBuild import List
  160. # Create a temporary working directory
  161. t = BoostBuild.Tester()
  162. # Create the needed files
  163. t.write("jamroot.jam", "")
  164. t.write("jamfile.jam", """
  165. exe hello : hello.cpp ;
  166. """)
  167. t.write("hello.cpp", """
  168. int main()
  169. {
  170. return 0;
  171. }
  172. """)
  173. t.run_build_system()
  174. # First, create a list of three pathnames.
  175. file_list = List("bin/$toolset/debug/") * List("hello.exe hello.obj")
  176. # Second, assert that those files were added as result of the last build system invocation.
  177. t.expect_addition(file_list)
  178. # Invoke the build system once again.
  179. t.run_build_system("clean")
  180. # Check if the files added previously were removed.
  181. t.expect_removal(file_list)
  182. # Remove temporary directories
  183. t.cleanup()
  184. </pre>
  185. <p>The <tt>test</tt> directory contains a file "template.py" which can be
  186. used as a start for your own tests.</p>
  187. <p>Overview of the most important methods of class <tt>Tester</tt> follows.
  188. </p>
  189. <h3><a name="sec-intro-changing">Changing the working directory</a></h3>
  190. <p>The class <tt>Tester</tt> creates a temporary directory in its
  191. constructor and changes to that directory. It can be modified by calling
  192. these methods:</p>
  193. <ul>
  194. <li><tt>set_tree</tt> -- sets the content of the working directory to be
  195. equal to the content of the specified directory. This method is
  196. preferable when directory tree for testing is large.</li>
  197. <li><tt>write</tt> -- sets the content of file in a working directory.
  198. This is optimal if you want to create a directory tree with 3-4 small
  199. files.</li>
  200. <li><tt>touch</tt> -- changes the modification times of a file</li>
  201. </ul>
  202. <h3><a name="sec-intro-examining">Examining the working directory and
  203. changing it</a></h3>
  204. <p>The method <tt>read</tt>, inherited from the <tt>TestCmd</tt> class, can
  205. be used to read any file in the working directory and check its content.
  206. <tt>Tester</tt> adds another method for tracking changes. Whenever the build
  207. system is run (using <a href="#method-run_build_system"><tt>run_build_system
  208. </tt></a>), the working dir state before and after running is recorded. In
  209. addition, difference between the two states -- i.e. lists of files that were
  210. added, removed, modified or touched -- are stored in two member variables -
  211. <tt>tree_difference</tt> and <tt>unexpected_difference</tt>.</p>
  212. <p>After than, the test author may specify that some change is expected, for
  213. example, by calling <tt>expect_addition("foo")</tt>. This call will check if
  214. the file was indeed added, and if so, will remove its name from the list of
  215. added files in <tt>unexpected_difference</tt>. Likewise, it is possible to
  216. specify that some changes are not interesting, for example a call to
  217. <tt>ignore("*.obj")</tt> will just remove every file with the ".obj"
  218. extension from <tt>unexpected_difference</tt>.</p>
  219. <p>When test has finished with expectations and ignoring, the member
  220. <tt>unexpected_difference</tt> will contain the list of all changes not yet
  221. accounted for. It is possible to assure that this list is empty by calling
  222. the <tt>expect_nothing_more</tt> member function.</p>
  223. <h3><a name="sec-intro-results">Test result</a></h3>
  224. <p>Any of the <tt>expect*</tt> methods below will fail the test if the
  225. expectation is not met. It is also possible to perform manually arbitrary
  226. test and explicitly cause the test to either pass or fail. Ordinary
  227. filesystem functions can be used to work with the directory tree. Methods
  228. <tt>pass_test</tt> and <tt>fail_test</tt> are used to explicitly give the
  229. test outcome.</p>
  230. <p>Typically, after test termination, the working directory is erased. See
  231. the <a href="#sec-command-line-options">"--preserve" command line option</a>
  232. for information on how to preserve the working directory content for failed
  233. tests for debugging purposes.</p>
  234. <h2 id="sec-reference">Reference documentation</h2>
  235. <p>The test system is composed of class <tt>Tester</tt>, derived form
  236. <tt>TestCmd.TestCmd</tt>, and helper class <tt>List</tt>. <tt>Tester</tt>
  237. and <tt>List</tt> methods are described below.</p>
  238. <p>The documentation frequently refers to <tt>filename</tt>. In all cases,
  239. files are specified in unix style: a sequence of components, separated by
  240. "/". This is true on all platforms. In some contexts a list of files is
  241. allowed. In those cases any object with a sequence interface is allowed.</p>
  242. <h3><a name="method-__init__">Method <tt>__init__(self, arguments="",
  243. executable="bjam", match=TestCmd.match_exact, boost_build_path=None,
  244. translate_suffixes=True, pass_toolset=True, use_test_config=True,
  245. ignore_toolset_requirements=True, workdir="", **keywords)</tt></a></h3>
  246. <p><b>Optional arguments:</b></p>
  247. <ul>
  248. <li><tt>arguments</tt>
  249. -- Arguments passed to the run executable.</li>
  250. <li><tt>executable</tt>
  251. -- Name of the executable to invoke.</li>
  252. <li><tt>match</tt>
  253. -- Function to use for compating actual and expected file contents.
  254. </li>
  255. <li><tt>boost_build_path</tt>
  256. -- Boost build path to be passed to the run executable.</li>
  257. <li><tt>translate_suffixes</tt>
  258. -- Whether to update suffixes on the the file names passed from the
  259. test script so they match those actually created by the current
  260. toolset. For example, static library files are specified by using
  261. the .lib suffix but when the 'gcc' toolset is used it actually
  262. creates them using the .a suffix.</li>
  263. <li><tt>pass_toolset</tt>
  264. -- Whether the test system should pass the specified toolset to the
  265. run executable.</li>
  266. <li><tt>use_test_config</tt>
  267. -- Whether the test system should tell the run executable to read in
  268. the test_config.jam configuration file.</li>
  269. <li><tt>ignore_toolset_requirements</tt>
  270. -- Whether the test system should tell the run executable to ignore
  271. toolset requirements.</li>
  272. <li><tt>workdir</tt>
  273. -- Indicates an absolute directory where the test will be run from.
  274. </li>
  275. </ul>
  276. <p><b>Optional arguments inherited from the base class:</b></p>
  277. <ul>
  278. <li><tt>description</tt>
  279. -- Test description string displayed in case of a failed test.</li>
  280. <li><tt>subdir</tt>
  281. -- List of subdirectories to automatically create under the working
  282. directory. Each subdirectory needs to be specified separately
  283. parent coming before its child.</li>
  284. <li><tt>verbose</tt>
  285. -- Flag that may be used to enable more verbose test system output.
  286. Note that it does not also enable more verbose build system output
  287. like the <a href="#sec-command-line-options">"--verbose" command
  288. line option</a> does.</li>
  289. </ul>
  290. <p><b>Effects:</b></p>
  291. <ol>
  292. <li>Remembers the current working directory in member
  293. <tt>original_workdir</tt>.</li>
  294. <li>Determines the location of the executable (<code>bjam</code> by
  295. default) and build system files, assuming that the current directory is
  296. <tt>tools/build/test</tt>. Formulates jam invocation command, which
  297. will include explicit setting for the <tt>BOOST_BUILD_PATH</tt> variable
  298. and arguments passed to this methods, if any. This command will be used
  299. by subsequent invocation of <a href="#method-run_build_system"><tt>
  300. run_build_system</tt></a>. Finally, initializes the base class.</li>
  301. <li>Changes the current working directory to the temporary working
  302. directory created by the base constructor.</li>
  303. <li>If you want to run a test in an existing directory, pass it as
  304. <tt>workdir</tt>.</li>
  305. <li> Most parameters passed to this constructor function may be overruled
  306. for each specific test system run using <a href=
  307. "#method-run_build_system"><tt>run_build_system</tt></a> parameters.
  308. </ol>
  309. <h3><a name="method-set_tree">Method <tt>set_tree(self,
  310. tree_location)</tt></a></h3>
  311. <p><b>Effects:</b></p>
  312. <p>Replaces the content of the current working directory with the content
  313. of directory at <tt>tree_location</tt>. If <tt>tree_location</tt> is not
  314. absolute pathname, it will be treated as relative to
  315. <tt>self.original_workdir</tt>. This methods also explicitly makes the
  316. copied files writeable.</p>
  317. <h3><a name="method-write">Method <tt>write(self, name,
  318. content)</tt></a></h3>
  319. <p><b>Effects:</b></p>
  320. <p>Writes the specified content to the file given by <tt>name</tt> under
  321. the temporary working directory. If the file already exists, it is
  322. overwritten. Any required directories are automatically created.</p>
  323. <h3><a name="method-copy">Method <tt>copy(self, src, dst)</tt></a></h3>
  324. <p><b>Effects:</b></p>
  325. <p>Equvivalent to <tt>self.write(self.read(src), dst)</tt>.</p>
  326. <h3><a name="method-touch">Method <tt>touch(self, names)</tt></a></h3>
  327. <p><b>Effects:</b></p>
  328. <p>Sets the access and modification times for all files in <tt>names</tt> to
  329. the current time. All the elements in <tt>names</tt> should be relative
  330. paths.</p>
  331. <h3><a name="method-run_build_system">Method <tt>run_build_system(self,
  332. extra_args="", subdir="", stdout=None, stderr="", status=0, match=None,
  333. pass_toolset=None, use_test_config=None, ignore_toolset_requirements=None,
  334. expected_duration=None, **kw)</tt></a></h3>
  335. <p><b>Effects:</b></p>
  336. <ol>
  337. <li>Stores the state of the working directory in
  338. <tt>self.previous_tree</tt>.</li>
  339. <li>Changes to <tt>subdir</tt>, if it is specified. It is relative to
  340. the <tt>original_workdir</tt> or the workdir specified in
  341. <tt>__init</tt>.</li>
  342. <li>Invokes the <tt>bjam</tt> executable, passing <tt>extra_args</tt>
  343. to it. The binary should be located under
  344. <tt>&lt;test_invocation_dir&gt;/../jam/src/bin.&lt;platform&gt;</tt>.
  345. This is to make sure tests use the version of jam build from CVS.</li>
  346. <li>Compares the stdout, stderr and exit status of build system
  347. invocation with values to appropriate parameters, if they are not
  348. <tt>None</tt>. If any difference is found, the test fails.</li>
  349. <li>If the <tt>expected_duration</tt> parameter is specified then it
  350. represents the maximal allowed time in seconds for the test to run. The
  351. test will be marked as failed if its duration is greater than the given
  352. <tt>expected_duration</tt> parameter value.</li>
  353. <li>Stores the new state of the working directory in <tt>self.tree</tt>.
  354. Computes the difference between previous and current trees and stores them
  355. in variables <tt>self.tree_difference</tt> and
  356. <tt>self.unexpected_difference</tt>. Both variables are instances of class
  357. <tt>tree.Trees_different</tt>, which have four attributes:
  358. <tt>added_files</tt>, <tt>removed_files</tt>, <tt>modified_files</tt> and
  359. <tt>touched_files</tt>. Each is a list of strings.</p></li>
  360. </ol>
  361. <h3><a name="method-read">Method <tt>read(self, name)</tt></a></h3>
  362. <p><b>Effects:</b></p>
  363. <p>Read the specified file and returns it content. Raises an exception is
  364. the file is absent.</p>
  365. <h3><a name="method-read_and_strip">Method <tt>read_and_strip(self, name)
  366. </tt></a></h3>
  367. <p><b>Effects:</b></p>
  368. <p>Read the specified file and returns it content, after removing trailing
  369. whitespace from every line. Raises an exception is the file is absent.</p>
  370. <p><b>Rationale:</b></p>
  371. <p>Although this method is questionable, there are a lot of cases when jam
  372. or shells it uses insert spaces. It seems that introducing this method is
  373. much simpler than dealing with all those cases.</p>
  374. <h3><a name="methods-expectations">Methods for declaring expectations</a>
  375. </h3>
  376. <p>Accordingly to the number of changes kinds that are detected, there are
  377. four methods that specify that test author expects a specific change to
  378. occur. They check <tt>self.unexpected_difference</tt>, and if the change is
  379. present there, it is removed. Otherwise, test fails.</p>
  380. <p>Each method accepts a list of names. Those names use <tt>/</tt> path
  381. separator on all systems. Additionally, the test system translates suffixes
  382. appropriately. For the test to be portable, suffixes should use Windows
  383. convention: <tt>exe</tt> for executables, <tt>dll</tt> for dynamic libraries
  384. and <tt>lib</tt> for static libraries. Lastly, the string "$toolset" in file
  385. names is replaced by the name of tested toolset.</p>
  386. <p><b>Note:</b> The <tt>List</tt> helper class might be useful to create
  387. lists of names.</p>
  388. <p><b>Note:</b> The file content can be examined using the
  389. <tt>TestCmd.read</tt> function.</p>
  390. <p>The members are:</p>
  391. <ul>
  392. <li>expect_addition</li>
  393. <li>expect_removal</li>
  394. <li>expect_modification</li>
  395. <li>expect_nothing</li>
  396. </ul>
  397. <p>Note that <tt>expect_modification</tt> is used to check that a either
  398. file content or timestamp has changed. The rationale is that some compilers
  399. change content even if sources does not change, and it's easier to have a
  400. method which checks for both content and time changes.</p>
  401. <p>There's also a member <tt>expect_nothing_more</tt>, which checks that all
  402. the changes are either expected or ignored, in other words that
  403. <tt>unexpected_difference</tt> is empty by now.</p>
  404. <p>Lastly, there's a method to compare file content with expected content:
  405. </p>
  406. <tt>expect_content(self, name, content, exact=0)</tt>
  407. <p>The method fails the test if the content of file identified by 'name' is
  408. different from 'content'. If 'exact' is true, the file content is used
  409. as-is, otherwise, two transformations are applied:</p>
  410. <ul>
  411. <li>The <tt>read_and_strip</tt> method is used to read the file, which
  412. removes trailing whitespace</li>
  413. <li>Each backslash in the file content is converted to forward slash.</li>
  414. </ul>
  415. <h3><a name="methods-ignoring">Methods for ignoring changes</a></h3>
  416. <p>There are five methods which ignore changes made to the working tree.
  417. They silently remove elements from <tt>self.unexpected_difference</tt>, and
  418. don't generate error if element is not found. They accept shell style
  419. wildcard.</p>
  420. <p>The following methods correspond to four kinds of changes:</p>
  421. <ul>
  422. <li>ignore_addition(self, wildcard)</li>
  423. <li>ignore_removal(self, wildcard)</li>
  424. <li>ignore_modification(self, wildcard)</li>
  425. <li>ignore_touch(self, wildcard)</li>
  426. </ul>
  427. <p>The method <tt>ignore(self, wildcard)</tt> ignores all the changes made
  428. to files that match a wildcard.</p>
  429. <h3><a name="methods-result">Methods for explicitly specifying results</a>
  430. </h3>
  431. <h4>Method <tt>pass_test(self, condition=1)</tt></h4>
  432. <div class="attention">
  433. At this moment, the method should not be used.
  434. </div>
  435. <h4>Method <tt>fail_test(self, condition=1)</tt></h4>
  436. <p><b>Effects:</b> Cause the test to fail if <tt>condition</tt> is true.</p>
  437. <h3><a name="class-list">Helper class <tt>List</tt></a></h3>
  438. The class has sequence interface and two additional methods.
  439. <h4>Method <tt>__init__(self, string)</tt></h4>
  440. <p><b>Effects:</b> Splits the string on unescaped spaces and tabs. The split
  441. components can further be retrieved using standard sequence access.</p>
  442. <h4>Method <tt>__mul__(self, other)</tt></h4>
  443. <p><b>Effects:</b> Returns an <tt>List</tt> instance, which elements are all
  444. possible concatenations of two string, first of which is from <tt>self</tt>,
  445. and second of which is from <tt>other</tt>.</p>
  446. <p>The class also defines <tt>__str__</tt> and <tt>__repr__</tt> methods.
  447. Finally, there's <tt>__coerce__</tt> method which allows to convert strings
  448. to instances of <tt>List</tt>.</p>
  449. <p><b>Example:</b></p>
  450. <pre>
  451. l = "a b" * List("c d")
  452. for e in l:
  453. print e
  454. </pre>
  455. <p>will output:</p>
  456. <pre>
  457. ac
  458. ad
  459. bc
  460. bd
  461. </pre>
  462. <hr>
  463. <p class="revision">Last modified: May 02, 2008</p>
  464. <p>&copy; Copyright Vladimir Prus 2002, 2003, 2004, 2005.<br>
  465. &copy; Copyright Jurko Gospodnetic 2008.<br>
  466. Distributed under the Boost Software License, Version 1.0.
  467. (See accompanying file LICENSE.txt or https://www.bfgroup.xyz/b2/LICENSE.txt)</p>
  468. </body>
  469. </html>