Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Initial import of source

  • Loading branch information...
commit 7218e3084d06cd9cbf48d6b5300bda23e530c9f4 1 parent 628d3e7
@yanne yanne authored
Showing with 19,665 additions and 0 deletions.
  1. +13 −0 COPYRIGHT.txt
  2. +72 −0 HACKING.txt
  3. +202 −0 LICENSE.txt
  4. +5 −0 MANIFEST.in
  5. +147 −0 atest/golden/another_resource.html
  6. +180 −0 atest/golden/golden_resource.html
  7. +483 −0 atest/golden/tests.html
  8. +70 −0 atest/golden/tsvtests.tsv
  9. +1 −0  atest/golden/varz.py
  10. +428 −0 atest/robotdiff.py
  11. +64 −0 atest/test_golden.py
  12. +322 −0 atest/ui_acceptance.html
  13. +182 −0 doc/exampleplugins/helloworld.py
  14. BIN  doc/ride.png
  15. +212 −0 package.py
  16. BIN  robot.bmp
  17. +13 −0 rundevel.py
  18. +5 −0 setup.cfg
  19. +45 −0 setup.py
  20. +22 −0 src/bin/ride.py
  21. +83 −0 src/robotide/__init__.py
  22. +16 −0 src/robotide/application/__init__.py
  23. +159 −0 src/robotide/application/application.py
  24. +131 −0 src/robotide/application/datamodel.py
  25. +88 −0 src/robotide/application/keywordcolorizer.py
  26. +91 −0 src/robotide/application/plugin.py
  27. +177 −0 src/robotide/application/plugingui.py
  28. +220 −0 src/robotide/application/pluginmanager.py
  29. +201 −0 src/robotide/application/preview.py
  30. +169 −0 src/robotide/application/recentfiles.py
  31. +118 −0 src/robotide/application/releasenotes.py
  32. +49 −0 src/robotide/context/__init__.py
  33. +2,455 −0 src/robotide/context/configobj.py
  34. +61 −0 src/robotide/context/logger.py
  35. +8 −0 src/robotide/context/settings.cfg
  36. +144 −0 src/robotide/context/settings.py
  37. +16 −0 src/robotide/editors/__init__.py
  38. +89 −0 src/robotide/editors/clipboard.py
  39. +133 −0 src/robotide/editors/dialoghelps.py
  40. +167 −0 src/robotide/editors/editordialogs.py
  41. +377 −0 src/robotide/editors/editors.py
  42. +64 −0 src/robotide/editors/eventhandler.py
  43. +60 −0 src/robotide/editors/fieldeditors.py
  44. +523 −0 src/robotide/editors/kweditor.py
  45. +129 −0 src/robotide/editors/listeditor.py
  46. +30 −0 src/robotide/errors.py
  47. +16 −0 src/robotide/model/__init__.py
  48. +144 −0 src/robotide/model/cache.py
  49. +433 −0 src/robotide/model/files.py
  50. +63 −0 src/robotide/model/importsettings.py
  51. +111 −0 src/robotide/model/keywords.py
  52. +40 −0 src/robotide/model/metadata.py
  53. +191 −0 src/robotide/model/settings.py
  54. +228 −0 src/robotide/model/tables.py
  55. +155 −0 src/robotide/model/tcuk.py
  56. +40 −0 src/robotide/robotapi.py
  57. +341 −0 src/robotide/spec/SSHLibrary.xml
  58. +883 −0 src/robotide/spec/SeleniumLibrary.xml
  59. +1,503 −0 src/robotide/spec/SwingLibrary.xml
  60. +15 −0 src/robotide/spec/__init__.py
  61. +178 −0 src/robotide/spec/spec.py
  62. +16 −0 src/robotide/ui/__init__.py
  63. +160 −0 src/robotide/ui/actions.py
  64. +121 −0 src/robotide/ui/dialogs.py
  65. +225 −0 src/robotide/ui/filedialogs.py
  66. +51 −0 src/robotide/ui/images.py
  67. +345 −0 src/robotide/ui/mainframe.py
  68. +43 −0 src/robotide/ui/namedialogs.py
  69. BIN  src/robotide/ui/process.png
  70. BIN  src/robotide/ui/robot.png
  71. +512 −0 src/robotide/ui/suitetree.py
  72. +59 −0 src/robotide/utils/__init__.py
  73. +100 −0 src/robotide/utils/components.py
  74. +232 −0 src/robotide/utils/contentassist.py
  75. +43 −0 src/robotide/utils/factory.py
  76. +82 −0 src/robotide/utils/misc.py
  77. +34 −0 src/robotide/utils/onscreenframe.py
  78. +173 −0 src/robotide/validators/__init__.py
  79. +14 −0 src/robotide/version.py
  80. +16 −0 src/robotide/writer/__init__.py
  81. +76 −0 src/robotide/writer/htmltemplate.py
  82. +91 −0 src/robotide/writer/template.py
  83. +269 −0 src/robotide/writer/writer.py
  84. +76 −0 utest/model/test_datamodel.py
  85. +218 −0 utest/model/test_getting_keywords.py
  86. +90 −0 utest/model/test_keywordspec.py
  87. +229 −0 utest/model/test_model.py
  88. +39 −0 utest/model/test_no_ride.py
  89. +112 −0 utest/model/test_parsing.py
  90. +76 −0 utest/model/test_serialization.py
  91. +77 −0 utest/model/test_settings.py
  92. +61 −0 utest/plugins/test_pluginmanager.py
  93. +3 −0  utest/plugins/test_plugins/not_plugin.py
  94. +18 −0 utest/plugins/test_plugins/plugin1.py
  95. +18 −0 utest/plugins/test_plugins/plugin2.py
  96. +39 −0 utest/resources/__init__.py
  97. +137 −0 utest/resources/mocks.py
  98. +170 −0 utest/resources/robotdata/.no_ride/no_ride.html
  99. +150 −0 utest/resources/robotdata/.no_ride/no_ride_resource.html
  100. +15 −0 utest/resources/robotdata/__init__.py
  101. +357 −0 utest/resources/robotdata/everything.html
  102. +10 −0 utest/resources/robotdata/invalid.html
  103. +13 −0 utest/resources/robotdata/libs/ArgLib.py
  104. +26 −0 utest/resources/robotdata/libs/LibSpecLibrary.xml
  105. +27 −0 utest/resources/robotdata/libs/OldStyleLibSpecLibrary.xml
  106. +27 −0 utest/resources/robotdata/libs/TestLib.py
  107. +170 −0 utest/resources/robotdata/minimal.html
  108. +142 −0 utest/resources/robotdata/put_into_python_path/PathResource.html
  109. +26 −0 utest/resources/robotdata/put_into_python_path/TestLib.xml
  110. +27 −0 utest/resources/robotdata/put_into_python_path/spec_resource.xml
  111. +127 −0 utest/resources/robotdata/resources/another_resource.html
  112. +1 −0  utest/resources/robotdata/resources/more_varz.py
  113. +1 −0  utest/resources/robotdata/resources/res_var_file.py
  114. +234 −0 utest/resources/robotdata/resources/resource.html
  115. +2 −0  utest/resources/robotdata/resources/resources2/even_more_resources.txt
  116. +1 −0  utest/resources/robotdata/resources/resources2/even_more_varz.py
  117. +138 −0 utest/resources/robotdata/resources/resources2/resource2.html
  118. +183 −0 utest/resources/robotdata/variables.html
  119. +3 −0  utest/resources/robotdata/varz.py
  120. +98 −0 utest/run_utests.py
  121. +46 −0 utest/settings/test_ride_settings.py
  122. +346 −0 utest/settings/test_settings.py
  123. +60 −0 utest/settings/testing_utils.py
  124. +25 −0 utest/ui/test_clipboard.py
  125. +41 −0 utest/ui/test_content_assist.py
  126. +185 −0 utest/ui/test_kweditor.py
  127. +273 −0 utest/ui/test_suitetree.py
  128. +107 −0 utest/utils/test_history.py
  129. +40 −0 utest/validators/test_arguments_validation.py
  130. +174 −0 utest/writer/test_template.py
View
13 COPYRIGHT.txt
@@ -0,0 +1,13 @@
+Copyright 2008 Nokia Siemens Networks Oyj
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
View
72 HACKING.txt
@@ -0,0 +1,72 @@
+= General =
+
+This document describes the technical process of contributing code in the RIDE
+project.
+
+In general, sending patches is the way to start contributing. Patches should
+follow the guidelines described below. After submitting some number of accepted
+patches, commit rights may be given.
+
+
+= Project information =
+
+RIDE is hosted in Google Code service [1]. All information about commits, code
+reviews and changes in issue tracker are sent to ride-code mailing list [2].
+For development discussion, robotframework-devel mailing list [3] is used.
+
+
+= Source code =
+
+Source code is hosted in the Google Code Subversion repository [4], which
+also supports read-only anonymous checkouts.
+
+
+= Coding guidelines =
+
+In general, all the code should be written according to Style Guide for Python
+Code [5] However, as stated in the Zen of Python, practicality beats purity.
+
+== Method names ==
+
+Typically, we use `lowercase_with_underscore` style for method names. Of
+course, when overriding wx methods, `AllCapitalized` style must be used.
+Additionally, there's a special case when writing event handler methods. We
+have chosen to name event handlers following this pattern: `OnEventName` (e.g.
+`OnMouseClick`).
+
+== Variable names ==
+
+Instance variables also follow the `lowercase_with_underscore` naming
+convention. Additionally, a leading underscore indicates that the variable is
+considered private.
+
+Global variables (provided there's really a need for such) use `ALL_CAPS`
+style.
+
+== Getters and setters ==
+
+We follow the Pythonic way of not implementing getters and setters in the case
+where direct attribute access is sufficient
+
+
+= Tests =
+
+Unfortunately we do not currently have high level automated test cases.
+However, all new code should have unit test written for it. These unit tests
+are included in the `utest` directory. To execute all unit tests, run
+
+ python utest/run_utests.py
+
+The `atest` folder contains some tests for serialization. These tests read data
+in RIDE and serialize it right back. Then both the original and modified suite
+is executed, and results compared. These test may be run with command (in atest
+directory)
+
+ python test_golden.py golden
+
+
+[1] http://code.google.com/p/robotframework-ride/
+[2] http://groups.google.com/group/robotframework-ride-code
+[3] http://groups.google.com/group/robotframework-devel
+[4] http://code.google.com/p/robotframework-ride/source/browse/
+[5] http://www.python.org/dev/peps/pep-0008/
View
202 LICENSE.txt
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
View
5 MANIFEST.in
@@ -0,0 +1,5 @@
+include src/robotide/spec/*.xml
+include src/robotide/ui/*.png
+include src/robotide/context/*.cfg
+include MANIFEST.in
+include COPYRIGHT.txt LICENSE.txt
View
147 atest/golden/another_resource.html
@@ -0,0 +1,147 @@
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="RobotIDE" />
+<style type="text/css">
+html {
+ font-family: Arial,Helvetica,sans-serif;
+ background-color: white;
+ color: black;
+}
+p {
+ max-width: 60em;
+}
+table {
+ border-collapse: collapse;
+ empty-cells: show;
+ margin: 1em 0em;
+ border: 0.1em solid black;
+}
+th, td {
+ border-style: solid;
+ border-width: 0.05em 0.1em;
+ border-color: black;
+ padding: 0.1em 0.2em;
+ height: 1.5em;
+}
+th {
+ background-color: rgb(192, 192, 192);
+ color: black;
+ border-width: 0.1em;
+ font-weight: bold;
+ text-align: center;
+ text-transform: capitalize;
+ letter-spacing: 0.1em;
+}
+/* Widths of named columns */
+col.name {
+ width: 10em;
+}
+.action, .value, .arg {
+ width: 15em;
+}
+/* Properties for the name column
+- td:first-child should work in CSS 2.1 avare browsers (tested in Firefox)
+- col.name is against specs but works in IE
+*/
+td:first-child, col.name {
+ background-color: rgb(240, 240, 240);
+ text-transform: capitalize;
+ letter-spacing: 0.1em;
+}
+/* required for IE */
+th {
+ font-style: normal;
+}
+</style>
+<title>Another Resource</title>
+</head>
+<body>
+<h1>Another Resource</h1>
+
+<table border="1">
+<colgroup span="99">
+<col class="name">
+<col class="value" span="4"></colgroup>
+<tr>
+<th>Setting</th>
+<th>Value</th>
+<th>Value</th>
+<th>Value</th>
+<th>Value</th>
+</tr>
+<tr>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+</table>
+
+<table border="1">
+<colgroup span="99">
+<col class="name">
+<col class="value" span="4"></colgroup>
+<tr>
+<th>Variable</th>
+<th>Value</th>
+<th>Value</th>
+<th>Value</th>
+<th>Value</th>
+</tr>
+<tr>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+</table>
+
+<table border="1">
+<colgroup span="99">
+<col class="name">
+<col class="action">
+<col class="arg" span="3"></colgroup>
+<tr>
+<th>Keyword</th>
+<th>Action</th>
+<th>Argument</th>
+<th>Argument</th>
+<th>Argument</th>
+</tr>
+<tr>
+<td><a name="keyword_Kw From Another Resource">Kw From Another Resource</a></td>
+<td>No Operation</td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td></td>
+<td>[Return]</td>
+<td>foo</td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+</table>
+
+</body>
+</html>
View
180 atest/golden/golden_resource.html
@@ -0,0 +1,180 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<meta name="generator" content="RobotIDE">
+<style type="text/css">
+html {
+ font-family: Arial,Helvetica,sans-serif;
+ background-color: white;
+ color: black;
+}
+p {
+ max-width: 60em;
+}
+table {
+ border-collapse: collapse;
+ empty-cells: show;
+ margin: 1em 0em;
+ border: 0.1em solid black;
+}
+th, td {
+ border-style: solid;
+ border-width: 0.05em 0.1em;
+ border-color: black;
+ padding: 0.1em 0.2em;
+ height: 1.5em;
+}
+th {
+ background-color: rgb(192, 192, 192);
+ color: black;
+ border-width: 0.1em;
+ font-weight: bold;
+ text-align: center;
+ text-transform: capitalize;
+ letter-spacing: 0.1em;
+}
+/* Widths of named columns */
+col.name {
+ width: 10em;
+}
+.action, .value, .arg {
+ width: 15em;
+}
+/* Properties for the name column
+- td:first-child should work in CSS 2.1 avare browsers (tested in Firefox)
+- col.name is against specs but works in IE
+*/
+td:first-child, col.name {
+ background-color: rgb(240, 240, 240);
+ text-transform: capitalize;
+ letter-spacing: 0.1em;
+}
+/* required for IE */
+th {
+ font-style: normal;
+}
+</style>
+<title>Golden Resource</title></head>
+
+
+<body>
+<h1>Golden Resource</h1>
+
+<table border="1">
+<colgroup span="99"><col class="name"><col class="value" span="4"></colgroup>
+<tbody><tr>
+<th>Setting</th>
+<th>Value</th>
+<th>Value</th>
+<th>Value</th>
+<th>Value</th>
+</tr>
+<tr>
+<td>Library</td>
+<td>OperatingSystem</td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td>Resource</td>
+<td>another_resource.html</td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+<tr><td></td><td></td><td></td><td></td><td></td></tr><tr><td>Documentation</td><td>This is resource file documentation</td><td></td><td></td><td></td></tr><tr>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+</tbody></table>
+
+<table border="1">
+<colgroup span="99"><col class="name"><col class="value" span="4"></colgroup>
+<tbody><tr>
+<th>Variable</th>
+<th>Value</th>
+<th>Value</th>
+<th>Value</th>
+<th>Value</th>
+</tr>
+<tr>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+</tbody></table>
+
+<table border="1">
+<colgroup span="99"><col class="name"><col class="action"><col class="arg" span="3"></colgroup>
+<tbody><tr>
+<th>Keyword</th>
+<th>Action</th>
+<th>Argument</th>
+<th>Argument</th>
+<th>Argument</th>
+</tr>
+<tr>
+<td><a name="keyword_Resource UK">Resource UK</a></td>
+<td>[Arguments]</td>
+<td>${value}</td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td></td>
+<td>[Documentation]</td>
+<td>This is a keyword from a resource file</td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td></td>
+<td>Repeat Keyword</td>
+<td>4 x</td>
+<td>No Operation</td>
+<td></td>
+</tr>
+<tr>
+<td></td>
+<td>[Return]</td>
+<td>${value}</td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td><a name="keyword_Curdir In Resource">Curdir In Resource</a></td>
+<td>Should Not Contain</td>
+<td>${CURDIR}</td>
+<td>golden</td>
+<td></td>
+</tr>
+<tr>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+</tbody></table>
+
+</body></html>
View
483 atest/golden/tests.html
@@ -0,0 +1,483 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head>
+<style type="text/css">
+html {
+ font-family: Arial,Helvetica,sans-serif;
+ background-color: white;
+ color: black;
+}
+p {
+ max-width: 60em;
+}
+table {
+ border-collapse: collapse;
+ empty-cells: show;
+ margin: 1em 0em;
+ border: 0.1em solid black;
+}
+th, td {
+ border-style: solid;
+ border-width: 0.05em 0.1em;
+ border-color: black;
+ padding: 0.1em 0.2em;
+ height: 1.5em;
+}
+th {
+ background-color: rgb(192, 192, 192);
+ color: black;
+ border-width: 0.1em;
+ font-weight: bold;
+ text-align: center;
+ text-transform: capitalize;
+ letter-spacing: 0.1em;
+}
+/* Widths of named columns */
+col.name {
+ width: 10em;
+}
+.action, .value, .arg {
+ width: 15em;
+}
+/* Properties for the name column
+- td:first-child should work in CSS 2.1 avare browsers (tested in Firefox)
+- col.name is against specs but works in IE
+*/
+td:first-child, col.name {
+ background-color: rgb(240, 240, 240);
+ text-transform: capitalize;
+ letter-spacing: 0.1em;
+}
+/* required for IE */
+th {
+ font-style: normal;
+}
+</style>
+<title>Golden Tests</title></head>
+<body>
+<h1>Golden Tests</h1>
+
+<table border="1">
+<colgroup span="99"><col class="name"><col class="value" span="4"></colgroup>
+<tbody><tr>
+<th>Setting</th>
+<th>Value</th>
+<th>Value</th>
+<th>Value</th>
+<th>Value</th>
+</tr>
+<tr>
+<td>Documentation</td>
+<td>Test cases for IDE compatibility\n<br>Documentation has a newline</td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+<tr><td></td><td></td><td></td><td></td><td></td></tr><tr>
+<td>Force Tags</td>
+<td>force1</td>
+<td>force 2</td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td>Default Tags</td>
+<td>d1</td>
+<td>d2</td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td>Suite Setup</td>
+<td>My Suite Setup</td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td>Suite Teardown</td>
+<td>My Suite Teardown</td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td>Test Setup</td>
+<td>My Test Setup</td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td>Test Teardown</td>
+<td>My Test Teardown</td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td>Test Timeout</td>
+<td>1 min</td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td>Meta: My Meta Data</td>
+<td>This has some interesting values</td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+
+<tr><td></td><td></td><td></td><td></td><td></td></tr><tr>
+<td>Resource</td>
+<td>golden_resource.html</td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+
+<tr>
+<td>Library</td>
+<td>OperatingSystem</td>
+<td></td>
+<td></td>
+<td></td>
+</tr><tr><td>Library</td><td>ArgLib</td><td>foo</td><td>bar</td><td></td></tr><tr><td>Variables</td><td>varz.py</td><td></td><td></td><td></td></tr><tr><td></td><td></td><td></td><td></td><td></td></tr>
+</tbody></table>
+
+<table border="1">
+<colgroup span="99"><col class="name"><col class="value" span="4"></colgroup>
+<tbody><tr>
+<th>Variable</th>
+<th>Value</th>
+<th>Value</th>
+<th>Value</th>
+<th>Value</th>
+</tr>
+<tr>
+<td>${SCALAR_VAR}</td>
+<td>Hello\n, World!</td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td>@{LIST}</td>
+<td>1</td>
+<td>2</td>
+<td>3</td>
+<td>4</td>
+</tr>
+<tr><td>${unicode}</td><td>§öäå</td><td></td><td></td><td></td></tr><tr>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+</tbody></table>
+
+<table border="1">
+<colgroup span="99"><col class="name"><col class="action"><col class="arg" span="3"></colgroup>
+<tbody><tr>
+<th>Test Case</th>
+<th>Action</th>
+<th>Argument</th>
+<th>Argument</th>
+<th>Argument</th>
+</tr>
+<tr>
+<td><a name="test_Passing_Test">Passing Test</a></td>
+<td>[Documentation]</td>
+<td>This is a passing test</td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td></td>
+<td>[Tags]</td>
+<td>tag1</td>
+<td>tag2</td>
+<td>tag3</td>
+</tr>
+<tr>
+<td></td>
+<td>[Timeout]</td>
+<td>20 seconds</td>
+<td></td>
+<td></td>
+</tr>
+<tr><td></td><td>Should Be Equal</td><td>${SCALAR VAR}</td><td>Hello\n, World!</td><td></td></tr><tr>
+<td></td>
+<td>Log Many</td>
+<td>Hello</td>
+<td>World</td>
+<td>${CURDIR}</td>
+</tr>
+<tr><td></td><td>...</td><td>@{LIST}</td><td>${UNICODE}</td><td></td></tr><tr><td></td><td>Log Many</td><td>1</td><td>2</td><td>3</td></tr><tr><td></td><td>...</td><td>4</td><td>5</td><td>6</td></tr><tr><td></td><td>...</td><td>7</td><td>8</td><td>9</td></tr><tr><td></td><td>...</td><td>10</td><td>11</td><td>12</td></tr><tr><td></td><td>Should Not Contain</td><td>${CURDIR}</td><td>golden</td><td></td></tr><tr><td></td><td>Curdir in Resource</td><td></td><td></td><td></td></tr><tr><td></td><td>Log</td><td>${var from file}</td><td></td><td></td></tr><tr>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td><a name="test_User_Keywords">User Keywords</a></td>
+<td>${ret} =</td>
+<td>User Keyword</td>
+<td>args</td>
+<td></td>
+</tr>
+<tr>
+<td></td>
+<td>Should Be Equal</td>
+<td>${ret}</td>
+<td>Success</td>
+<td></td>
+</tr>
+<tr>
+<td></td>
+<td>Resource UK</td>
+<td>my value</td>
+<td></td>
+<td></td>
+</tr>
+<tr><td></td><td></td><td></td><td></td><td></td></tr><tr><td>Library With Args</td><td>${man} =</td><td>Get Mandatory</td><td></td><td></td></tr><tr>
+<td></td>
+<td>${def} =</td><td>Get Default</td>
+
+<td></td>
+<td></td>
+</tr>
+<tr><td></td><td>Should Be Equal</td><td>${man}${def}</td><td>foobar</td><td></td></tr><tr><td></td><td></td><td></td><td></td><td></td></tr><tr>
+<td><a name="test_Challenging_Test">Challenging Test</a></td>
+<td>[Setup]</td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td></td>
+<td>:: FOR</td>
+<td>${i}</td>
+<td>IN</td>
+<td>@{list}</td>
+</tr>
+<tr>
+<td></td>
+<td></td>
+<td>Log</td>
+<td>${i}</td>
+<td></td>
+</tr>
+<tr>
+<td></td>
+<td>:: FOR</td>
+<td>${x}</td>
+<td>${y}</td>
+<td>IN RANGE</td>
+</tr>
+<tr>
+<td></td>
+<td>...</td>
+<td>10</td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td></td>
+<td></td>
+<td>${result} =</td>
+<td>Evaluate</td>
+<td>${x}*${y}</td>
+</tr>
+<tr>
+<td></td>
+<td></td>
+<td>Log</td>
+<td>${result}</td>
+<td></td>
+</tr>
+<tr>
+<td></td>
+<td>:: PARALLEL</td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td></td>
+<td></td>
+<td>Fail Unless</td>
+<td>@{list}[0]==1</td>
+<td></td>
+</tr>
+<tr>
+<td></td>
+<td></td>
+<td>Log</td>
+<td>Inside Paralell Block</td>
+<td></td>
+</tr>
+<tr>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td><a name="test_Failing_Teardown">Failing Teardown</a></td>
+<td>[Teardown]</td>
+<td>Fail</td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td></td>
+<td>No Operation</td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+<tr><td>Unicode §</td><td>Log</td><td>½¼¤</td><td></td><td></td></tr><tr><td></td><td>Should Be Equal</td><td>${unicode}</td><td>§öäå</td><td></td></tr><tr>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+</tbody></table>
+
+<table border="1">
+<colgroup span="99"><col class="name"><col class="action"><col class="arg" span="3"></colgroup>
+<tbody><tr>
+<th>Keyword</th>
+<th>Action</th>
+<th>Argument</th>
+<th>Argument</th>
+<th>Argument</th>
+</tr>
+<tr>
+<td><a name="keyword_My_Test_Setup">My Test Setup</a></td>
+<td>Log</td>
+<td>Hello from test setup</td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td><a name="keyword_My_Suite_Setup">My Suite Setup</a></td>
+<td>Log</td>
+<td>Hello from suite setup</td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td><a name="keyword_My_Test_Teardown">My Test Teardown</a></td>
+<td>Log</td>
+<td>Hello from test teardown</td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td><a name="keyword_My_Suite_Teardown">My Suite Teardown</a></td>
+<td>Log</td>
+<td>Hello from suite teardown</td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td><a name="keyword_User_Keyword">User Keyword</a></td>
+<td>[Documentation]</td>
+<td>This is a User Keyword</td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td></td>
+<td>[Arguments]</td>
+<td>${arg}</td>
+<td>${default}=default</td>
+<td>@{list}</td>
+</tr>
+<tr>
+<td></td>
+<td>Log</td>
+<td>${arg}</td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td></td>
+<td>Log</td>
+<td>${default}</td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td></td>
+<td>Log Many</td>
+<td>@{list}</td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td></td>
+<td>[Return]</td>
+<td>Success</td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+</tbody></table>
+
+</body></html>
View
70 atest/golden/tsvtests.tsv
@@ -0,0 +1,70 @@
+T S V T E S T S
+
+*Setting* *Value* *Value* *Value* *Value* *Value* *Value* *Value*
+Resource golden_resource.html
+Library OperatingSystem
+Documentation Test cases for IDE compatibility
+Suite Setup My Suite Setup
+Suite Teardown My Suite Teardown
+Test Setup My Test Setup
+Test Teardown My Test Teardown
+Default Tags d1 d2
+Force Tags force1 force 2
+Test Timeout 1 min
+Meta: My Meta Data This has some interesting values
+
+
+*Variable* *Value* *Value* *Value* *Value* *Value* *Value* *Value*
+${SCALAR_VAR} Hello, World!
+@{LIST} 1 2 3 4
+${unicode} §öäå
+
+
+*Test Case* *Action* *Argument* *Argument* *Argument* *Argument* *Argument* *Argument*
+Passing Test [Documentation] This is a passing test
+ [Tags] tag1 tag2 tag3
+ [Timeout] 20 seconds
+ Log Many Hello World ${CURDIR} @{LIST} ${UNICODE}
+ Log Many 1 2 3 4 5 6
+ ... 7 8 9 10 11 12
+ Should Not Contain ${CURDIR} golden
+ Curdir in Resource
+
+User Keywords ${ret} = User Keyword args
+ Should Be Equal ${ret} Success
+ Resource UK my value
+
+Challenging Test [Setup]
+ :: FOR ${i} IN @{list}
+ Log ${i}
+ :: FOR ${x} ${y} IN RANGE 10
+ ${result} = Evaluate ${x}*${y}
+ Log ${result}
+ :: PARALLEL
+ Fail Unless @{list}[0]==1
+ Log Inside Paralell Block
+
+Failing Teardown No Operation
+ [Teardown] Fail
+
+Unicode § Log ½¼¤
+ Should Be Equal ${unicode} §öäå
+
+
+*Keyword* *Action* *Argument* *Argument* *Argument* *Argument* *Argument* *Argument*
+My Test Setup Log Hello from test setup
+
+My Suite Setup Log Hello from suite setup
+
+My Test Teardown Log Hello from test teardown
+
+My Suite Teardown Log Hello from suite teardown
+
+User Keyword [Arguments] ${arg} ${default}=default @{list}
+ [Documentation] This is a User Keyword
+ Log ${arg}
+ Log ${default}
+ Log Many @{list}
+ [Return] Success
+
+
View
1  atest/golden/varz.py
@@ -0,0 +1 @@
+var_from_file = "Hello from variable file"
View
428 atest/robotdiff.py
@@ -0,0 +1,428 @@
+#!/usr/bin/env python
+
+# Copyright 2008 Nokia Siemens Networks Oyj
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+"""Diff Tool for Robot Framework Outputs
+
+Usage: robotdiff.py [options] input_files
+
+This script compares two or more Robot Framework output files and creates a
+report where possible differences between test case statuses in each file
+are highlighted. Main use case is verifying that results from executing same
+test cases in different environments are same. For example, it is possible to
+test that new Robot Framework version does not affect test results. Another
+usage is comparing earlier test results with newer ones to find out possible
+status changes and added test cases.
+
+Options:
+ -r --report file HTML report file (created from the input files).
+ Default is 'robotdiff.html'.
+ -n --name name * Name for test run. Different test runs can be named
+ with this option. However, there must be as many
+ names as there are input files. By default the name
+ of the input files are used as names. Input files
+ having same file name are distinguished by adding
+ as many parent directories to the names as is needed.
+ -t --title title Title for the generated diff report. The default
+ title is 'Diff Report'.
+ -E --escape what:with * Escape certain characters which are problematic in
+ console. 'what' is the name of the character to
+ escape and 'with' is the string to escape it with.
+ Available character to escape:
+ <--------------------ESCAPES------------------------>
+ Example:
+ --escape space:_ --title My_Fine_Diff_Report
+ -h -? --help Print this usage instruction.
+
+Options that can be specified multiple times are marked with an asterisk (*).
+
+Examples:
+$ robotdiff.py output1.xml output2.xml output3.xml
+$ robotdiff.py --name Env1 --name Env2 smoke1.xml smoke2.xml
+"""
+
+import os
+import sys
+
+from robot import utils
+from robot.output import TestSuite
+from robot.errors import DataError, Information
+
+
+def main(args):
+ opts, paths = _process_args(args)
+ diff = DiffRobotOutputs(opts['report'], opts['title'])
+ names = _get_names(opts['name'], paths)
+ for path, name in zip(paths, names):
+ try:
+ diff.add_suite(path, name)
+ except DataError, err:
+ exit(error=str(err))
+ diff.serialize()
+ print "Report: %s" % utils.cygpath(diff.close())
+
+def _process_args(cliargs):
+ ap = utils.ArgumentParser(__doc__, arg_limits=(2, sys.maxint))
+ try:
+ opts, paths = ap.parse_args(cliargs, unescape='escape', help='help',
+ check_args=True)
+ except Information, msg:
+ exit(msg=str(msg))
+ except DataError, err:
+ exit(error=str(err))
+ return opts, [ utils.normpath(path) for path in paths ]
+
+def _get_names(names, paths):
+ if len(names) == 0:
+ return [None] * len(paths)
+ if len(names) == len(paths):
+ return names
+ exit(error="Different number of names (%d) and inputs (%d)"
+ % (len(names), len(paths)))
+
+
+def exit(rc=0, error=None, msg=None):
+ if error:
+ print error, "\n\nUse '--help' option to get usage information."
+ if rc == 0:
+ rc = 255
+ if msg:
+ print msg
+ rc = 1
+ sys.exit(rc)
+
+
+class DiffRobotOutputs:
+
+ def __init__(self, outpath=None, title=None):
+ if outpath is None:
+ outpath = 'robotdiff.html'
+ if title is None:
+ title = 'Diff Report'
+ self._output = open(utils.normpath(outpath), 'w')
+ self._writer = utils.HtmlWriter(self._output)
+ self.title = title
+ self.column_names = []
+ self.suites_and_tests = {}
+
+ def add_suite(self, path, column_name):
+ if column_name is None:
+ column_name = path
+ column_name = self._get_new_column_name(column_name)
+ self.column_names.append(column_name)
+ suite = TestSuite(path)
+ # Creates links to logs
+ link = self._get_loglink(path, self._output.name)
+ self._set_suite_links(suite, link)
+ self._add_suite(suite, column_name)
+
+ def _get_loglink(self, inpath, target):
+ """Finds matching log file and return link to it or None."""
+ indir, infile = os.path.split(inpath)
+ logname = os.path.splitext(infile.lower())[0]
+ if logname.endswith('output'):
+ logname = logname[:-6] + 'log'
+ for item in os.listdir(indir):
+ name, ext = os.path.splitext(item.lower())
+ if name == logname and ext in ['.html','.htm','.xhtml']:
+ logpath = os.path.join(indir, item)
+ return utils.get_link_path(logpath, target)
+ return None
+
+ def _set_suite_links(self, suite, link):
+ suite.link = link
+ for sub_suite in suite.suites:
+ self._set_suite_links(sub_suite, link)
+ for test in suite.tests:
+ test.link = link
+
+ def _get_new_column_name(self, column_name):
+ if self.column_names.count(column_name) == 0:
+ return column_name
+ count = 0
+ for name in self.column_names:
+ if name.startswith(column_name):
+ count += 1
+ return column_name + '_%d' % (count)
+
+ def _add_suite(self, suite, column_name):
+ self._add_to_dict(suite, column_name)
+ for sub_suite in suite.suites:
+ self._add_suite(sub_suite, column_name)
+ for test in suite.tests:
+ self._add_to_dict(test, column_name)
+
+ def _add_to_dict(self, s_or_t, column_name):
+ name = s_or_t.longname.replace('_', ' ')
+ keys = self.suites_and_tests.keys()
+ found = False
+ for key in keys:
+ if utils.normalize(name, caseless=True, spaceless=True) == \
+ utils.normalize(key, caseless=True, spaceless=True):
+ found = True
+ foundkey = key
+ if not found:
+ self.suites_and_tests[name] = [(column_name, s_or_t)]
+ else:
+ self.suites_and_tests[foundkey].append((column_name, s_or_t))
+
+ def serialize(self):
+ self._write_start()
+ self._write_headers()
+ for name, value in self._get_sorted_items(self.suites_and_tests):
+ self._write_start_of_s_or_t_row(name, value)
+ for column_name in self.column_names:
+ #Generates column containg status
+ s_or_t = self._get_s_or_t_by_column_name(column_name, value)
+ self._write_s_or_t_status(s_or_t)
+ self._writer.end('tr', newline=True)
+ self._writer.end('table', newline=True)
+ self._write_end()
+
+ def close(self):
+ self._output.close()
+ return self._output.name
+
+ def _write_s_or_t_status(self, s_or_t):
+ if s_or_t is not None:
+ self._col_status_content(s_or_t)
+ else:
+ col_status = 'col_status not_available'
+ self._writer.element('td', 'N/A', {'class': col_status})
+
+ def _col_status_content(self, s_or_t):
+ status = s_or_t.status
+ col_status = 'col_status %s' % status.lower()
+ self._writer.start('td', {'class': col_status})
+ if s_or_t.link is not None:
+ type = self._get_type(s_or_t)
+ link = '%s#%s_%s' % (s_or_t.link, type, s_or_t.longname)
+ self._writer.element('a', status, {'class': status.lower(),
+ 'href': link,
+ 'title': s_or_t.longname })
+ else:
+ self._writer.content(status)
+ self._writer.end('td')
+
+ def _get_type(self, s_or_t):
+ if dir(s_or_t).count('tests') == 1:
+ return 'suite'
+ else:
+ return 'test'
+
+ def _write_start_of_s_or_t_row(self, name, value):
+ row_status = self._get_row_status(value)
+ self._writer.element('th', name, {'class': row_status})
+
+ def _get_sorted_items(self, suites_and_tests):
+ items = suites_and_tests.items()
+ items.sort(lambda x, y: cmp(x[0], y[0]))
+ return items
+
+ def _get_row_status(self, items):
+ if len(items) > 0:
+ status = self._get_status(items[0])
+ else:
+ return 'none'
+ for item in items:
+ if self._get_status(item) != status:
+ return 'diff'
+ return 'all_%s' % (status.lower())
+
+ def _get_status(self, item):
+ return item[1].status
+
+ def _get_s_or_t_by_column_name(self, column_name, items):
+ for item in items:
+ if column_name == item[0]:
+ return item[1]
+ return None
+
+ def _write_headers(self):
+ self._writer.start('table')
+ self._writer.start('tr')
+ self._writer.element('th', 'Name', {'class': 'col_name'})
+ for name in self.column_names:
+ name = name.replace(self._get_prefix(self.column_names), '')
+ self._writer.element('th', name, {'class': 'col_status'})
+ self._writer.end('tr')
+
+ def _get_prefix(self, paths):
+ paths = [os.path.dirname(p) for p in paths ]
+ dirs = []
+ for path in paths:
+ if path.endswith(os.sep):
+ dirs.append(path)
+ else:
+ if path != '' and path[-1] != os.sep:
+ dirs.append(path + os.sep)
+ else:
+ dirs.append(path)
+ prefix = os.path.commonprefix(dirs)
+ while len(prefix) > 0:
+ if prefix.endswith(os.sep):
+ break
+ prefix = prefix[:-1]
+ return prefix
+
+ def _write_start(self):
+ self._output.write(START_HTML)
+ self._output.write("<title>%s</title>" % (self.title))
+ self._output.write("</head>\n<body><h1>%s</h1></br>\n" % (self.title))
+ self._output.write('<div class="spacer">&nbsp;</div>')
+
+ def _write_end(self):
+ self._writer.end('body')
+ self._writer.end('html')
+
+
+START_HTML = '''
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta http-equiv="Expires" content="Mon, 20 Jan 2001 20:01:21 GMT" />
+
+<style media="all" type="text/css">
+
+ /* Generic Table Styles */
+
+ table {
+ background: white;
+ border: 1px solid black;
+ border-collapse: collapse;
+ empty-cells: show;
+ margin: 0px 1px;
+ }
+ th, td {
+ border: 1px solid black;
+ padding: 1px 5px;
+ }
+ th {
+ background: #C6C6C6;
+ color: black;
+ }
+
+ .diff{
+ background: red;
+ }
+
+ .all_pass{
+ background: #00f000;
+ }
+
+ .all_fail{
+ background: yellow;
+ }
+
+
+ /* Test by Suite/Tag Tables */
+
+ table.tests_by_suite, table.tests_by_tag {
+ width: 100%;
+ }
+ .col_name {
+ width: 13em;
+ font-weight: bold;
+ }
+ .col_status {
+ width: 5em;
+ text-align: center;
+ }
+ .pass{
+ color: #00f000;
+ }
+ .fail{
+ color: red;
+ }
+</style>
+<style media="all" type="text/css">
+
+ /* Generic styles */
+
+ body {
+ font-family: sans-serif;
+ font-size: 0.8em;
+ color: black;
+ padding: 6px;
+ }
+ h2 {
+ margin-top: 1.2em;
+ }
+
+
+ /* Misc Styles */
+
+ .not_available {
+ color: gray; /* no grey in IE */
+ font-weight: normal;
+ }
+
+ a:link, a:visited {
+ text-decoration: none;
+
+ }
+ a:hover {
+ text-decoration: underline;
+ color: purple;
+ }
+
+ /* Headers */
+
+ .header {
+ width: 58em;
+ margin: 6px 0px;
+ }
+ h1 {
+ margin: 0px;
+ width: 73%;
+ float: left;
+ }
+ .times {
+ width: 26%;
+ float: right;
+ text-align: right;
+ }
+ .generated_time, .generated_ago {
+ font-size: 0.9em;
+ }
+ .spacer {
+ font-size: 0.8em;
+ clear: both;
+ }
+</style>
+
+<style media="print" type="text/css">
+ body {
+ background: white;
+ padding: 0px;
+ font-size: 9pt;
+ }
+ a:link, a:visited {
+ color: black;
+ }
+ .header, .failbox, .passbox, table.statistics {
+ width: 100%;
+ }
+ .generated_ago {
+ display: none;
+ }
+</style>
+'''
+
+
+if __name__ == '__main__':
+ main(sys.argv[1:])
View
64 atest/test_golden.py
@@ -0,0 +1,64 @@
+#!/usr/bin/env python
+
+import os
+import sys
+import shutil
+from tempfile import TemporaryFile
+from subprocess import call, STDOUT
+
+ORIGDIR = 'golden'
+OUTDIR = 'tmp'
+TARGETDIR = os.path.join(OUTDIR, 'tests')
+RIDETARGETDIR = os.path.join(OUTDIR, 'ride-tests')
+
+
+def setup():
+ if os.path.exists(OUTDIR):
+ shutil.rmtree(OUTDIR)
+ for name in [ OUTDIR, TARGETDIR, RIDETARGETDIR]:
+ os.mkdir(name)
+ for name in os.listdir(ORIGDIR):
+ path = os.path.join(ORIGDIR, name)
+ if os.path.isfile(path):
+ shutil.copy(path, TARGETDIR)
+
+def run_original_tests():
+ print 'Running original tests...'
+ _run_tests(['-l', 'orig.html', '-o', 'orig.xml', TARGETDIR])
+
+def use_ride():
+ for name in os.listdir(ORIGDIR):
+ path = os.path.join(ORIGDIR, name)
+ if os.path.isfile(path):
+ newname = os.path.join(RIDETARGETDIR, name)
+ if not path.endswith('.py'):
+ print "Processing '%s' with IDE" % path
+ ride_cmd = [ 'python', '../src/robotide/__init__.py', path, newname ]
+ call(ride_cmd)
+ else:
+ print "Copying '%s' -> '%s'" % (path, newname)
+ shutil.copy(path, newname)
+
+
+def _run_tests(opt_args):
+ command = [ 'pybot', '-r', 'none', '-d', OUTDIR, '-N', 'Golden_Tests',
+ '-P', os.path.join('..', 'utest', 'resources', 'robotdata') ]
+ ret = call(command + opt_args, shell=os.name=='nt')
+
+def run_modified_tests():
+ print 'Running processed tests...'
+ _run_tests(['-l', 'ride.html', '-o', 'ride.xml', RIDETARGETDIR])
+
+def diff():
+ print 'Diffing outputs...'
+ call(['python', 'robotdiff.py', '-r', os.path.join(OUTDIR, 'diff.html'),
+ os.path.join(OUTDIR, 'orig.xml'), os.path.join(OUTDIR, 'ride.xml')])
+
+
+if __name__ == '__main__':
+ setup()
+ run_original_tests()
+ use_ride()
+ run_modified_tests()
+ diff()
+
View
322 atest/ui_acceptance.html
@@ -0,0 +1,322 @@
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="RobotIDE" />
+<style type="text/css">
+html {
+ font-family: Arial,Helvetica,sans-serif;
+ background-color: white;
+ color: black;
+}
+p {
+ max-width: 60em;
+}
+table {
+ border-collapse: collapse;
+ empty-cells: show;
+ margin: 1em 0em;
+ border: 0.1em solid black;
+}
+th, td {
+ border-style: solid;
+ border-width: 0.05em 0.1em;
+ border-color: black;
+ padding: 0.1em 0.2em;
+ height: 1.5em;
+}
+th {
+ background-color: rgb(192, 192, 192);
+ color: black;
+ border-width: 0.1em;
+ font-weight: bold;
+ text-align: center;
+ text-transform: capitalize;
+ letter-spacing: 0.1em;
+}
+/* Widths of named columns */
+col.name {
+ width: 10em;
+}
+.action, .value, .arg {
+ width: 15em;
+}
+/* Properties for the name column
+- td:first-child should work in CSS 2.1 avare browsers (tested in Firefox)
+- col.name is against specs but works in IE
+*/
+td:first-child, col.name {
+ background-color: rgb(240, 240, 240);
+ text-transform: capitalize;
+ letter-spacing: 0.1em;
+}
+/* required for IE */
+th {
+ font-style: normal;
+}
+</style>
+<title>Ui Acceptance</title>
+</head>
+<body>
+<h1>Ui Acceptance</h1>
+
+<table border="1">
+<colgroup span="99">
+<col class="name">
+<col class="value" span="4"></colgroup>
+<tr>
+<th>Setting</th>
+<th>Value</th>
+<th>Value</th>
+<th>Value</th>
+<th>Value</th>
+</tr>
+<tr>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+</table>
+
+<table border="1">
+<colgroup span="99">
+<col class="name">
+<col class="value" span="4"></colgroup>
+<tr>
+<th>Variable</th>
+<th>Value</th>
+<th>Value</th>
+<th>Value</th>
+<th>Value</th>
+</tr>
+<tr>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+</table>
+
+<table border="1">
+<colgroup span="99">
+<col class="name">
+<col class="action">
+<col class="arg" span="3"></colgroup>
+<tr>
+<th>Test Case</th>
+<th>Action</th>
+<th>Argument</th>
+<th>Argument</th>
+<th>Argument</th>
+</tr>
+<tr>
+<td>It Should Be Possible To Open Existing File Suite</td>
+<td>Open Existing File Suite</td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td></td>
+<td>All Resource Files Imported By Suites Should Be Opened</td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td>It Should Be Possible To Open Existing Directory Suite</td>
+<td>Open Existing Directory Suite</td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td></td>
+<td>All Test Suites Inside The Directory Should Be Opened</td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td></td>
+<td>All Resource Files Imported By Suites Should Be Opened</td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td>It Should Be Possible To Create New File Project</td>
+<td>Create New File Project</td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td></td>
+<td>Add A Simple Test Case</td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td></td>
+<td>Serialize And Verify Correct Test Case File</td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td>It Should Be Possible To Create New Directory Project</td>
+<td>Create New Directory Project</td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td></td>
+<td>Add Simple User Keyword</td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td></td>
+<td>Serialize And Verify Correct Suite Initialization File</td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td></td>
+<td>Add New Test Suite</td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td></td>
+<td>Add Simple Test Case</td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td></td>
+<td>Serialize And Verify Correct Test Case File</td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td>It Should Be Possible To Open Resource Files</td>
+<td>Open Existing File Suite</td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td></td>
+<td>Open Resource File</td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+</table>
+
+<table border="1">
+<colgroup span="99">
+<col class="name">
+<col class="action">
+<col class="arg" span="3"></colgroup>
+<tr>
+<th>Keyword</th>
+<th>Action</th>
+<th>Argument</th>
+<th>Argument</th>
+<th>Argument</th>
+</tr>
+<tr>
+<td>All Resource Files Imported By Suites Should Be Opened</td>
+<td>Resource Files Imported Directly Should Be Opened</td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td></td>
+<td>Resource Files Imported Through Other Resource Files Should Be Opened</td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td></td>
+<td>Resource File Imports With Variable In Them Should Work If The Variable Is Defined</td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+<tr>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+<td></td>
+</tr>
+</table>
+
+</body>
+</html>
View
182 doc/exampleplugins/helloworld.py
@@ -0,0 +1,182 @@
+"""A Sample Plugin
+
+
+ For a module to be valid plugin it must define a function named
+ init_plugin which takes a single argument which is a pointer to
+ the RobotFrame.
+
+ This method is responsible for creating an instance of a class
+ that derives from robotide.plugins.Plugin, and returning a handle
+ to that object.
+
+"""
+
+import cStringIO
+import wx
+import zlib
+from robotide.application import Plugin
+
+ID_ABOUT = wx.NewId()
+ID_SHOW_HELLO = wx.NewId()
+ID_SHOW_TAB = wx.NewId()
+MENU_TITLE = "H&ello"
+TOOLBAR_BITMAP = wx.BitmapFromImage(wx.ImageFromStream(cStringIO.StringIO(
+ zlib.decompress(
+ 'x\xda\x01\xf5\x02\n\xfd\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10' +
+ '\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08' +
+ '\x08\x08\x08|\x08d\x88\x00\x00\x02\xacIDAT8\x8du\x92[H\x93a\x18\xc7\x7f\xef' +
+ '\xb7\xafa\xd3\xdc\xda\x9c\x19V\xae9\x02\xb3\xb2\x03\x98\x87\xbc\x902#1:X\xe4' +
+ 'Ut\x82\xe8&\xa2\x82I\x18D\x11Rt\xa0n*\x02\x91\x021\xa4n:PR\x82\x91#\xc5J2m' +
+ '\x98a\xda\xb22\xac\x9c\xee\xe8\xf7\xbd]\x8c,t=\xf0\\=\xff\xf7\xc7\xff\xf9' +
+ '\xbf\x8f\x90R2\xb5*k\x1eY\x81+@\x05`\x9c&\x88U\x13pP\xfd\xcf\xb0vK\x81s\xd3' +
+ '\xd6\xc2LT\x83\x12Wp\xbf\xad\xbf\xe4\xd6S\xef\xc3i\x80\xca\x9aGI@YE\x91\x0b' +
+ '\x7f\x08\xc2\x13\x92\xa8\x06\x9a\x04M\x07M\x97\x08\xa0,\xd7\x81\xa7\xe7\x8b+' +
+ '\x9e\x03kJr\x82A\x11\x82\xf1\x88D\xd3\x89\x01t\xf9\x0f$&L6\x19\x89\xe7o\xe4' +
+ '\xfbhH\xd3\xa5DUb\xe2\t]2\xa13\xd9\x10\xcbm,\x14e\xd2\xc1\xfeU65\xc9\xa8T' +
+ '\x17\xd8\xb5C\xddY\xc7d\xe33\'\x15E.\x14!\x00\xc1\xe0\x0f\xc9\xc8\xb8d\xaeY' +
+ '\x90:K\xe1~[?\xbd\xbe\x9f\xef\xc5\x9f_p\x17\xd9\x0eg\x98\x03\x17\x02RG\x98l' +
+ '\xf4e\xecc\xc4\x96\x0fB\xa1d\xc5|\xf6\x94.\x06\xe0\xe7X\x98;\xcf\xfbhz5\xd8' +
+ '\x05l\x99t\x90\xa6\x06\xd6\xdb\x97\x14c\xb7\xcf\xe6E{\x07\x06\xcfyfF\r\xccMO' +
+ '\xbf\xd9\xc4\xa5\x82\x8d\xb9\x8e\xcc\x07m\xfd4\xbd\x1a\x0c\x01g\xea\xdd\xa5' +
+ '\xa7\x80\xbf+\xa8\xd6\xc4oy\x9bwcN\x90X\x1d\xd9\x04\xc7~a\xb4\xa4q\xeb\xb5' +
+ '\x9eS\x9c3/\xf3\xf0\xb5g\xe3@u\xbd\xbb\xf4\xe2\xbf\x81M\x02Z"\xc5oJ\xfa\xdbe' +
+ 'J\xce\x1a\xb1t\xd9R\xc2\x9aBg\x87G\xfa\xd4\xd5\xe9\xbe\xceO\xfb\xeb\xdd\xa57' +
+ '\xe2\xdd\x83\n\x90V^o\xf8:\xb4\xd6\xb5\xfd\xcb0\x86\xf0\x0345\t\x950=Cs\xb8' +
+ '\xdd8\xd0`\xb5\xcf\xa8\xc5\x1d\xef9\x08\xcb\x86\x06\xe1\xf7+\xa7\x8e\xee\\YU' +
+ '\\\xe9T\x9a[=DB\x82h\x10\x96\xe7\xe4\xf1\xf2a\xafv\xf5\xee\x8b\xd3&\xd3\xd8I' +
+ '\x7f\xf3\x81iw\xaff\x99>\x1eYS\x98u|\xc5\xba\x85<\xfe\x00~K>\xe1\x00\x84\x04' +
+ '<y+\xc9^\xe92\xec\x1a\xee:\xe1\xed\xf5\x06\x80\xb3\xd3\x1c\xf8\xceeK_\xc6' +
+ '\x01\xea\xd8\xc1xb*Z@\x12\tB4\n\x13\x9a\xc08:L\x95\xb3\x11K\xd7e\x9c\xd5=b*@' +
+ '\t&:Z\xbd\x1dm\x0cx\xbc(*\x18\xcd\x02S\x8a\xc0<_\x90\x9c\n?\xba\xdb\x19\xe8|' +
+ 'N\xd4\xba\xa8%n\x88\xba\xc5Q\x9e\x16\t\xcd\xfb\xdc\xfai\xdb\xbb\xeb\xf7\xf6&' +
+ '$\x18g\x0b)\x0cR\xd3\xb4`8\x1a\xb4\x88\xe1:\xf3\xb2\x19\xb5\x8am\xc1\xe7x' +
+ '\x80\xdf\xbc\xe2\x18&\xc4\xcd][\x00\x00\x00\x00IEND\xaeB`\x82\x80\xe3^\xa7' ))))
+
+
+class HelloWorldPlugin(Plugin):
+ """A simple RIDE plugin
+
+ This plugin creates a notebook tab, a menu item and a toolbar
+ item. The toolbar item will only be created if the main app
+ has a toolbar (which it doesn't in version 0.15.1)
+ """
+
+ def __init__(self, manager=None):
+ Plugin.__init__(self, manager)
+ self.id = "example.hello_world"
+ self.name = "Hello World Plugin"
+ self.version = "0.2"
+ self.active = False
+ self._panel = None
+
+ def OnPublication(self,message):
+ """Handle publications from the main frame"""
+ # N.B. The text widget can be destroyed if the user closes the
+ # tab while the plugin is enabled, so we only log publications
+ # if the window is there.
+ if self.text:
+ self.text.AppendText("Received a publication:\n")
+ self.text.AppendText(" Topic: %s\n" % ".".join(message.topic))
+ self.text.AppendText(" Data:\n")
+ for key in message.data.keys():
+ self.text.AppendText(" %s = %s\n" % (key, message.data[key]))
+ self.text.AppendText("\n")
+
+ def deactivate(self):
+ """Deactivates this plugin."""
+ self._remove_from_notebook()
+ self._remove_from_menubar()
+ self._remove_from_toolbar()
+ self.manager.unsubscribe(self.OnPublication)
+ self.active = False
+
+ def activate(self):
+ """Make the plugin available"""
+ self._add_to_notebook()
+ self._add_to_menubar()
+ self._add_to_toolbar()
+ self.manager.subscribe(self.OnPublication, ("core"))
+ self.active = True
+
+ def OnAbout(self, event):
+ """Displays a dialog about this plugin"""
+ info = wx.AboutDialogInfo()
+ info.Name = self.name
+ info.Version = self.version
+ info.Description = self.__doc__
+ info.Developers = ["Bryan Oakley, Orbitz Worldwide"]
+ wx.AboutBox(info)
+
+ def OnSayHello(self, event):
+ """A handler for the menu and toolbar widgets"""
+ dialog = wx.MessageDialog(self.manager.get_frame(), "Hello, World!", "Hello, world", style=wx.OK)
+ dialog.ShowModal()
+
+ def OnShowTab(self, event):
+ """Show the notebook tab, creating it if it doesn't exist"""
+ if not self._panel:
+ self._add_to_notebook()
+ self.manager.show_page(self._panel)
+
+ def _add_to_notebook(self):
+ """Add a tab for this plugin to the notebook"""
+ notebook = self.manager.get_notebook()
+ if notebook:
+ self._panel = wx.Panel(notebook)
+ button = wx.Button(self._panel, ID_SHOW_HELLO, "Hello, world!")
+ self.text = wx.TextCtrl(self._panel, style=wx.TE_MULTILINE)
+ sizer = wx.BoxSizer(wx.VERTICAL)
+ sizer.Add(button,0)
+ sizer.Add(self.text, 1, wx.EXPAND|wx.ALL, border=8)
+ self._panel.SetSizer(sizer)
+ button.Bind(wx.EVT_BUTTON, self.OnSayHello)
+ notebook.AddPage(self._panel, "Hello, world!", select=False)
+
+ def _remove_from_notebook(self):
+ """Remove the tab for this plugin from the notebook"""
+ notebook = self.manager.get_notebook()
+ if notebook:
+ notebook.DeletePage(notebook.GetPageIndex(self._panel))
+
+ def _add_to_toolbar(self):
+ """Add a button to the toolbar for this plugin"""
+ toolbar = self.manager.get_tool_bar()
+ if toolbar:
+ toolbar.AddLabelTool(ID_SHOW_HELLO,"Say Hello",TOOLBAR_BITMAP, shortHelp="Say Hello")
+
+ def _remove_from_toolbar(self):
+ """Remove the button for this plugin from the toolbar"""
+ toolbar = self.manager.get_tool_bar()
+ if toolbar:
+ toolbar.RemoveTool(ID_SHOW_HELLO)
+
+ def _add_to_menubar(self):
+ """Add a menu item on the menubar for this plugin
+
+ The menu item will be added to the left of the Help menu.
+ """
+ menubar = self.manager.get_menu_bar()
+ if menubar:
+ hello_menu = wx.Menu()
+ pos = menubar.FindMenu("Help")
+ if pos >= 0:
+ menubar.Insert(pos, hello_menu, MENU_TITLE)
+ else:
+ menubar.Append(hello_menu, MENU_TITLE)
+
+ hello_menu.Append(ID_SHOW_TAB, "Show Notebook Tab", "Show and select the Hello, world notebook tab")
+ hello_menu.Append(ID_SHOW_HELLO, "Say Hello", "Prints Hello World")
+ hello_menu.AppendSeparator()
+ hello_menu.Append(ID_ABOUT, "About this plugin", "Show information about this plugin")
+ wx.EVT_MENU(self.manager.get_frame(), ID_SHOW_TAB, self.OnShowTab)
+ wx.EVT_MENU(self.manager.get_frame(), ID_ABOUT, self.OnAbout)
+ wx.EVT_MENU(self.manager.get_frame(), ID_SHOW_HELLO, self.OnSayHello)
+
+ def _remove_from_menubar(self):
+ """Remove the menubar item from the menubar for this plugin"""
+ menubar = self.manager.get_menu_bar()
+ if menubar:
+ pos = menubar.FindMenu(MENU_TITLE)
+ if pos >= 0:
+ menubar.Remove(pos)
+
View
BIN  doc/ride.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
212 package.py
@@ -0,0 +1,212 @@
+#!/usr/bin/env python
+
+# Copyright 2008-2009 Nokia Siemens Networks Oyj
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Packaging script for RIDE
+
+Usage: package.py command version_number [release_tag]
+
+Argument 'command' can have one of the following values:
+ - sdist : create source distribution
+ - wininst : create Windows installer
+ - all : create both packages
+ - version : update only version information in 'src/robot/version.py'
+
+'version_number' must be a version number in format 'x.y(.z)', 'trunk' or
+'keep'. With 'keep', version information is not updated.
+
+'release_tag' must be either 'alpha', 'beta', 'rc' or 'final', where all but
+the last one can have a number after the name like 'alpha1' or 'rc2'. When
+'version_number' is 'trunk', 'release_tag' is automatically assigned to the
+current date.
+
+This script uses 'setup.py' internally. Distribution packages are created
+under 'dist' directory, which is deleted initially. Depending on your system,
+you may need to run this script with administrative rights (e.g. with 'sudo').
+
+Examples:
+ package.py sdist 0.17 final
+ package.py wininst keep
+ package.py all 0.19 alpha
+ package.py sdist trunk
+ package.py version trunk
+"""
+
+import sys
+import os
+import shutil
+import re
+import time
+import csv
+from urllib2 import urlopen
+from string import Template
+from StringIO import StringIO
+
+from robot.utils import HtmlWriter, html_escape
+
+
+ROOT_PATH = os.path.dirname(__file__)
+DIST_PATH = os.path.join(ROOT_PATH, 'dist')
+BUILD_PATH = os.path.join(ROOT_PATH, 'build')
+RIDE_PATH = os.path.join(ROOT_PATH, 'src', 'robotide')
+SETUP_PATH = os.path.join(ROOT_PATH, 'setup.py')
+VERSION_PATH = os.path.join(RIDE_PATH, 'version.py')
+VERSIONS = [re.compile('^\d+\.\d+(\.\d+)?$'), 'trunk', 'keep']
+RELEASES = [re.compile('^alpha\d*$'), re.compile('^beta\d*$'),
+ re.compile('^rc\d*$'), 'final']
+VERSION_CONTENT = """# Automatically generated by 'package.py' script.
+
+VERSION = '%(version_number)s'
+RELEASE = '%(release_tag)s'
+TIMESTAMP = '%(timestamp)s'
+
+def get_version(sep=' '):
+ if RELEASE == 'final':
+ return VERSION
+ return VERSION + sep + RELEASE
+
+if __name__ == '__main__':
+ import sys
+ print get_version(*sys.argv[1:])
+"""
+
+def sdist(*version_info):
+ version(*version_info)
+ _clean()
+ _create_sdist()
+ _announce()
+
+def wininst(*version_info):
+ version(*version_info)
+ _clean()
+ if _verify_platform(*version_info):
+ _create_wininst()
+ _announce()
+
+def all(*version_info):
+ version(*version_info)
+ _clean()
+ _create_sdist()
+ if _verify_platform(*version_info):
+ _create_wininst()
+ _announce()
+
+def version(version_number, release_tag=None):
+ _verify_version(version_number, VERSIONS)
+ if version_number == 'keep':
+ _keep_version()
+ elif version_number =='trunk':
+ _update_version(version_number, '%d%02d%02d' % time.localtime()[:3])
+ else:
+ _update_version(version_number, _verify_version(release_tag, RELEASES))
+ _create_release_notes(version_number)
+
+def _verify_version(given, valid):
+ for item in valid:
+ if given == item or (hasattr(item, 'search') and item.search(given)):
+ return given
+ raise ValueError
+
+def _update_version(version_number, release_tag):
+ timestamp = '%d%02d%02d-%02d%02d%02d' % time.localtime()[:6]
+ vfile = open(VERSION_PATH, 'w')
+ vfile.write(VERSION_CONTENT % locals())
+ vfile.close()
+ print 'Updated version to %s %s' % (version_number, release_tag)
+
+def _keep_version():
+ sys.path.insert(0, RIDE_PATH)
+ from version import get_version
+ print 'Keeping version %s' % get_version()
+
+def _create_release_notes(version):
+ changes = _download_and_format_issues(version)
+ _update_release_notes_plugin(changes)
+
+def _download_and_format_issues(version):
+ URL = Template('http://code.google.com/p/robotframework-ride/issues/csv?'
+ 'sort=priority+type&colspec=ID%20Type%20Priority%20Summary'
+ '&q=target%3A${version}&can=1')
+